Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Test a method that returns a void

Wanted to Unit Test a method in the following Class

public class DeviceAuthorisationService : IDeviceAuthorisationService
{
    private DeviceDetailsDTO deviceDetailsDTO = null;
    private IDeviceAuthorisationRepositiory deviceAuthorisationRepositiory;

    public DeviceAuthorisationService(IDeviceAuthorisationRepositioryService paramDeviceAuthorisationRepository)
    {
        deviceAuthorisationRepositiory = paramDeviceAuthorisationRepository;
    }

    public void AuthoriseDeviceProfile(long paramUserID, string paramClientMakeModel)
    {
        if (deviceDetailsDTO == null)
            GetCellPhoneDetails(userID);

        if (deviceDetailsDTO.IsDeviceSelected == false)
            throw new SomeCustomExceptionA();

        if (deviceDetailsDTO.CellPhoneMakeModel.ToLower() != paramClientMakeModel.ToLower())
            throw new SomeCustomExceptionB;
    }

    public void UpdateDeviceStatusToActive(long userID)
    {
        if (deviceDetailsDTO == null)
            throw new InvalidOperationException("UnAuthorised Device Profile Found Exception");

        if (deviceDetailsDTO.PhoneStatus != (short)Status.Active.GetHashCode())
            deviceAuthorisationRepositiory.UpdatePhoneStatusToActive(deviceDetailsDTO.DeviceID);
    }

    private void GetCellPhoneDetails(long userID)
    {
        deviceDetailsDTO = deviceAuthorisationRepositiory.GetSelectedPhoneDetails(userID);

        if (deviceDetailsDTO == null)
            throw new SomeCustomException()
    }

}

Note:

  • Method Name = AuthoriseDeviceProfile returns void
  • The method checks userSentMakeModel against the one stored in the db match
  • If it matches - it simply returns (ie does not change any state)

How will we unit test this method?

  • Have mocked the Repo
  • Have covered scenario of "THROWS EXCEPTION"
  • Question is how to unit test the scenario of ALL WENT WELL ie user;s makeModel matched with repository;s makeModel

Any design suggestions to make this testable is most welcome Thanks in advance.

like image 333
Venu b Avatar asked Dec 11 '12 12:12

Venu b


People also ask

How do you return a void unit test?

You can do it by using ref keyword. First Create a void method with a ref parameter in your Class Library Solution. Out goal is to test this void method in unit test. Calling the methodRef in Test Class.

How do you unit test a void method without arguments?

Your modified program can ask for user input, call the function, then print the output. A testing framework can supply the input from a list of inputs to test, and check the outputs against the expected values. To test as-is, you'd have to intercept the input and output streams.

Can JUnit test void method?

In this example, we have learned that how we can JUnit Test Void Method. We have also learned that how to catch the exception if it is thrown by a void method. Actually testing mechanism is same for all methods, but void methods are special as we don't have any returning value to be matched for testing.


5 Answers

Since your method returns void, it probably has some side-effect that you can test/assert on.

In your case, an option would be to provide a mock instance of IDeviceAuthorisationRepositioryService. You can then check if a call to UpdatePhoneStatusToActive has happened. Here is a solution using Moq:

var mock = new Mock<IDeviceAuthorisationRepositioryService>();

var service = new DeviceAuthorisationService(mock.Object);
service.UpdateDeviceStatusToActive(....);

mock.Verify(x => service.UpdatePhoneStatusToActive(), Times.Never());
like image 70
alexn Avatar answered Oct 12 '22 18:10

alexn


If a method is void, then it should have some observable side-effect - otherwise it's pointless. So instead of testing the return value, you test the side-effects. In this case, it looks like those a probably around which exceptions are thrown in which situations.

(Here, "throws an exception" is deemed a side-effect; you could also think of it as an implicit kind of return value of course...)

like image 34
Jon Skeet Avatar answered Oct 12 '22 16:10

Jon Skeet


Inject a mocked repository. Test if certain methods on the repository are called.

like image 41
Z.D. Avatar answered Oct 12 '22 17:10

Z.D.


You can set exception expectancies on your unit tests. In nUnit it looks like this:

[Test]
[ExpectedException(typeof(InvalidOperationException))]
public void TestAuthoriseFail()
{
    // do something that should make the tested method throw the exception
}
like image 28
Phil Gan Avatar answered Oct 12 '22 17:10

Phil Gan


Even if your method returns void, it must be doing something that is useful for you (otherwise it would be a pointless method to have).

From your code, I'm guessing there are essentially 2 flavours of 'useful' things that the AuthoriseDeviceProfile method is doing:

  • calling the GetSelectedPhoneDetails method on the IDeviceAuthorisationRepositiory
  • throwing various exceptions based on certain conditions

Therefore to unit test the method, you should do two things that correspond to this:

  • Inject a mock IDeviceAuthorisationRepositiory and have it record and/or assert whether GetSelectedPhoneDetails is called
  • Exercise test methods that induce the various exceptions, and capture them as they are thrown to verify that:
    • an exception is in fact thrown
    • the exception that is thrown is the appropriate one for each scenario
like image 32
Chamila Chulatunga Avatar answered Oct 12 '22 17:10

Chamila Chulatunga