Solved

Unit testing, moq, best practices

Posted on 2016-10-14
7
37 Views
Last Modified: 2016-10-14
I have a setting repository that contains application settings that are stored in the database.
I currently have no unit test code coverage. The IService interface only contains one method for Get()
Get() returns a collection of Setting.

1. What should I be testing?
2.. What should I be naming the tests?

    public class SettingServiceTest
    {
        private Mock<ISettingRepository> mockRepository;
        private ISettingService service;

        [TestInitialize]
        public void Inititalize()
        {
            mockRepository = new Mock<ISettingRepository>();
            service = new SettingService(mockRepository.Object);
        }

        [TestMethod]
        public void Test_Get_Settings()
        {
            mockRepository
                 .Setup(x => x.Get())
                 .Returns(It.IsAny<List<Setting>>);

            var result = service.Get();
            mockRepository.Verify(x => x.Get());
        }
    }

Open in new window

0
Comment
Question by:JRockFL
  • 5
  • 2
7 Comments
 
LVL 75

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 500 total points
ID: 41844050
What should I be testing?
Your service layer. You can also test your UI layer via coded-UI test. I find those tests harder to work with and modify compared to regular unit tests. Testing your database would be covered by an integration test.

What should I be naming the tests?
I prefer the convention:

System Under Test____Condition____Expected Result

In this way, when a test fails, you can easily see within the Test Explorer what is failing. Also, developers coming behind you can see what the test *should* be doing.
0
 
LVL 8

Assisted Solution

by:JRockFL
JRockFL earned 0 total points
ID: 41844066
Thank you for your reply. Yes, I agree that I should be testing the service layer and the naming convention.
I was looking for the specific tests I should be doing against this service layer for settings.

Test_Get_Settings_Returns_List_Of_Settings
Would this be an appriopate test name?
Would there be value to this test? How else should I test it?
0
 
LVL 75

Accepted Solution

by:
käµfm³d   👽 earned 500 total points
ID: 41844154
Would this be an appriopate test name?
IMO, no. You don't want to test the data type that's being returned. What if you change from a List<string> to an integer? Now you have to go and rename that test (and maybe others).

In this specific case, there's not really much to test. Your method simply invokes the database. This method is effectively a wrapper around the data layer (since you don't have any business logic here). You  *could* test that you are invoking the database method--which you could do using Moq's Verify methods, as you are already doing. Having said that, many people would consider that to be testing an implementation detail, which they would advise against. The danger with tests of this nature is that if the implementation changes, then the corresponding tests have to change as well. (I'm personally on the fence as to whether or not this is a good or a bad thing.)
0
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 
LVL 75

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 500 total points
ID: 41844158
I would write the test thus:

public class SettingServiceTest
{
    private Mock<ISettingRepository> mockRepository;
    private ISettingService service;

    [TestInitialize]
    public void Inititalize()
    {
        mockRepository = new Mock<ISettingRepository>();
        service = new SettingService(mockRepository.Object);
    }

    [TestMethod]
    public void Get_Called__Always__ISettingRepository_Get_Called()
    {
        // Arrange
        mockRepository
             .Setup(x => x.Get())
             .Returns(It.IsAny<List<Setting>>);

        // Act
        var result = service.Get();
        
        // Assert
        mockRepository.Verify(x => x.Get());
    }
}

Open in new window


I explicitly include "Arrange", "Act", and "Assert" comments to make it clear to others how the test is structured, including where each section begins/ends. In this case, because of the aforementioned wrapper behavior, I wouldn't have a condition, and I would simply denote the condition as "Always". This hopefully makes it clear what the intent of the code and/or test is.
0
 
LVL 75

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 500 total points
ID: 41844160
P.S.

In the name, I don't include "SettingService" in the System Under Test (sut) because the class itself denotes this. All tests within this class should correspond to the SettingService. Therefore, each method's sut is simply the method being invoked. (I usually quantify a "unit" to be a method, but this is not a hard and fast rule. A unit could be more than one method, or even an entire class. You have to determine what is a sensible "unit" for your environment.)
0
 
LVL 75

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 500 total points
ID: 41844167
P.P.S.

And I just realized that you have the service scoped to the class. I would not suggest this. If your service doesn't maintain any state internally (i.e. private fields), then you are probably safe. But it is very easy for another developer to come behind you, add some state, and suddenly 100 tests are broken and you have no idea why. Also, you want your unit tests to be independent of each other. This ensures no side effects.

Tests typically run pretty fast (because you will be mocking out database, web service, and other dependencies). There is no reason not to new up an instance of the service per test. Worry about refactoring the tests later if you encounter performance issues.

Same thing with the mock. You don't want to inadvertently have one mock object's state affecting a different test.

e.g.

public class SettingServiceTest
{
    [TestMethod]
    public void Get_Called__Always__ISettingRepository_Get_Called()
    {
        // Arrange
        Mock<ISettingRepository> mockRepository = new Mock<ISettingRepository>();
        ISettingService service = new SettingService(mockRepository.Object);

        mockRepository
             .Setup(x => x.Get())
             .Returns(It.IsAny<List<Setting>>);

        // Act
        var result = service.Get();
        
        // Assert
        mockRepository.Verify(x => x.Get());
    }
}

Open in new window

0
 
LVL 8

Author Comment

by:JRockFL
ID: 41844502
Thank you for much. That has been very helpful.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

We all know that functional code is the leg that any good program stands on when it comes right down to it, however, if your program lacks a good user interface your product may not have the appeal needed to keep your customers happy. This issue can…
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
Many functions in Excel can make decisions. The most simple of these is the IF function: it returns a value depending on whether a condition you describe is true or false. Once you get the hang of using the IF function, you will find it easier to us…
Both in life and business – not all partnerships are created equal. As the demand for cloud services increases, so do the number of self-proclaimed cloud partners. Asking the right questions up front in the partnership, will enable both parties …

861 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

24 Experts available now in Live!

Get 1:1 Help Now