user2918107
user2918107

Reputation: 123

How to write a unit test for a method which calls other services

I have a following method which is calling another service , but there is a some data manipulation before calling internal service. Please see below

   public async Task<myObject> Save(string server,string username, myObject element)
            {
                string temp = element.Class + "_" + element.Description + "_" + username;
                var saveData = new string[] { element.Name, temp};
                var response = await datService.save(server, saveData);
                var result = response.TomyObject(); // this is the extension method to convert response to myObject. 
                return result ;
            }

What will be the best way to unit test? I tried following but just want to make sure I am doing the "correct" way.

public async Task Save_Success()
        {
            //ARRANGE         
            var element = new myObject
            {
                Name = "Test",
                Description = "Test Save", 
                Class = "test class"


            };
            string temp = element.Class+ "_" + element.Description + "_" + username;
            var saveData = new string[] { element.Name, temp};
            var response = new anotherObject
            {

                Name= "Test",              
                MyArray = new objArray
                {
                    P0 = saveData[0],
                    P1 = saveData[1]                   

                },
                Error = ""

            };




            var datService = new Mock<IDataService>();
            datService.Setup(x => x.Save(It.IsAny<string>(), It.IsAny<string[]>()).Returns(Task.FromResult(response));
            var myClass = new MyClass(datService.Object);
            //ACT
            var result = await myClass.Save("testServer","testUser", element);
            // ASSERT
            Assert.AreEqual(response.MyArray.P0, result.Class);
        }

Here is the extension method

 public static myObject TomyObject(this anotherObject response)
        {
            var entity = new myObject();

            entity.Name = response.Name;           
           if(response.MyArray!= null && response.MyArray.P1 != "")
            {
                string[] details = response.MyArray.P1.Split('_');
                entity.Class = details[0];
                entity.Description = details[1];


            }

            return entity;

        }

Upvotes: 1

Views: 1912

Answers (1)

crgolden
crgolden

Reputation: 4634

Here is how you could test your extension method:

anotherObject response = new anotherObject
{
    Name = "TestName",
    MyArray = new objArray
    {
        P1 = "Val1_Val2"
    }
};
var result = response.TomyObject();
Assert.Equal("TestName", result.Name);
Assert.Equal("Val1", result.Class);
Assert.Equal("Val2", result.Description);

The key is to have your unit tests only test one unit of work. If you want to test your extension method, write a test for it in isolation. Once you start including multiple units of work (i.e. the IDataService), you are actually testing a system and it becomes an integration test.

UPDATE:

On this line in your Save_Success test:

// ASSERT
Assert.AreEqual(response.MyArray.P0, result.Class);

You are actually testing something that is not the responsibility of the Save method (setting the Class property is actually the responsibility of your TomyObject, which could be tested separately).

To verify the Save method is doing what it's supposed to, you could do this:

// ASSERT
datService.Verify(x => x.Save(It.IsAny<string>(), It.IsAny<string[]>()), Times.Once);

That way, you're only testing that the Save method is doing what it's explicitly responsible for doing.

Upvotes: 1

Related Questions