how to assert mock state simultaneous with thrown exception - c#

I'm following TDD and ran into a problem where if I make one test succeed, two others fail due to an exception being thrown. Well, I want to throw the exception, but I also want to verify the other behaviors. For instance:
public class MyTests {
[Fact]
public void DoSomethingIsCalledOnceWhenCheckerIsTrue()
{
var checker = new Mock<IChecker>();
var doer = new Mock<IDoer>();
checker.Setup(x => x.PassesCheck).Returns(true);
var sut = new ThingThatChecksAndDoes(checker.Object,doer.Object);
sut.CheckAndDo();
checker.VerifyGet(x => x.PassesCheck, Times.Once());
doer.Verify(x => x.Do(),Times.Once());
}
[Fact]
public void DoSomethingIsNeverCalledWhenCheckerIsFalse()
{
var checker = new Mock<IChecker>();
var doer = new Mock<IDoer>();
checker.Setup(x => x.PassesCheck).Returns(false);
var sut = new ThingThatChecksAndDoes(checker.Object,doer.Object);
sut.CheckAndDo();
doer.Verify(x => x.Do(),Times.Never());
}
[Fact]
public void ThrowCheckDidNotPassExceptionWhenCheckDoesNotPass()
{
var checker = new Mock<IChecker>();
var doer = new Mock<IDoer>();
checker.Setup(x => x.PassesCheck).Returns(false);
var sut = new ThingThatChecksAndDoes(checker.Object,doer.Object);
Assert.Throws<CheckDidNotPassException>(() => { sut.CheckAndDo(); });
}
}
What are my choices for approaching this? What, if any, would be the "preferred" choice?

Your 1st and 2nd test passes. Then when you add the 3rd test the rest of the tests fails!.
With TDD
"Avoid altering existing tests that pass. Instead, add new tests.
Change existing tests only when the user requirements change."
I also assume your SUT (System Under Test) as below
public void CheckAndDo() {
var b = _checker.PassesCheck;
if (b) {
_doer.Do();
}
throw new CheckDidNotPassException();
}
In your SUT, when you throw a new exception, obviously it has an effect on the rest of the behaviour the way you have implemented execution logic.
So the option here would be to change the existing test(s).
Give it a well named test method, and Assert both exception and the verification.
[Test]
public void CheckAndDo_WhenPassesCheckTrue_DoCalledOnlyOnceAndThrowsCheckDidNotPassException()
{
var checker = new Mock<IChecker>();
var doer = new Mock<IDoer>();
checker.Setup(x => x.PassesCheck).Returns(true);
var sut = new ThingThatChecksAndDoes(checker.Object, doer.Object);
Assert.Throws<CheckDidNotPassException>(() => { sut.CheckAndDo(); });
doer.Verify(x => x.Do(), Times.Once());
}
Few other things you need to consider:
a. TDD produces good Unit tests. Good means, readable, maintainable and trustworthy Unit Tests.
Your test method names and the calls to SUT are poorly named. I guess this is just for the demo/Stackoverflow question. But I suggest in future you provide a real world example with real names other than "Do" "Something"
Having ambiguous names does not help from the TDD point of view as you are designing your system in small based on the requirements.
b. Publish the correct code.
In your first test you passing Mock types
var checker = new Mock<IChecker>();
var doer = new Mock<IDoer>();
var sut = new ThingThatChecksAndDoes(checker, doer);
You should pass the instances i.e (checker.Object)

When I test similar methods
I do not write a test, that x.Do() is not called
I check that exception is thrown and x.Do() is not called in one test because these two Assertions are related to the same flow.

Related

Unit Testing a Service with Moq & xUnit

Sorry, this is likely a very amateur question, but I am struggling to understand how to use Moq properly. I am quite new to unit testing as a whole, but I think I'm starting to get the hang of it.
So here's my question... I have this snippet of code below which is using a TestServer in Visual Studio that I using for am Unit Testing... I'm trying to mock IGamesByPublisher so that my test is not reliant on data in the repository (or would it be better to mock GamesByPublisher?... Or do I need to do both?)
public static TestServerWithRepositoryService => new TestServer(services =>
{
services.AddScoped<IGamesByPublisher, GamesByPublisher();
}).AddAuthorization("fake.account", null);
[Fact] // 200 - Response, Happy Path
public async Task GamesByPublisher_GamesByPublisherLookup_ValidRequestData_Produces200()
{
// Arrange
var server = ServerWithRepositoryService;
// Act
var response = await server.GetAsync(Uri);
// Assert
Assert.NotNull(response);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}
Here is the IGamesByPublisher
public interface IGamesByPublisher interface.
{
Task<IEnumerable<Publisher>> Execute(GamesByPublisherQueryOptions options);
}
}
I tried
public static TestServerWithRepositoryService => new TestServer(services =>
{
services.AddScoped<Mock<IGamesByPublisher>, Mock<GamesByPublisher>>();
}).AddAuthorization("fake.account", null);
And then I tried
// Not exactly what I attempted, but that code is long gone...
var mock = new Mock<IGamesByPublisher >();
var foo = new GamesByPublisherQueryOptions();
mock.Setup(x => x.Execute(foo)).Returns(true);
I didn't really find great documentation on using Moq, just the quick start guide on GitHub, which I wasn't sure how to apply (probably my own level of experience at fault there...).
I am obviously missing some fundamentals on using Moq...
You were close.
public static TestServerWithRepositoryService => new TestServer(services => {
var mock = new Mock<IGamesByPublisher>();
var publishers = new List<Publisher>() {
//...populate as needed
};
mock
.Setup(_ => _.Execute(It.IsAny<GamesByPublisherQueryOptions>()))
.ReturnsAsync(() => publishers);
services.RemoveAll<IGamesByPublisher>();
services.AddScoped<IGamesByPublisher>(sp => mock.Object);
}).AddAuthorization("fake.account", null);
The above creates the mock, sets up its expected behavior to return a list of publishers any time Execute is invoked with a GamesByPublisherQueryOptions.
It then removes any registrations of the desired interface to avoid conflicts and then registers the service to return the mock any time the interface is requested to be resolved.

FakeItEasy not verifying call for Full Framework SignalR test

I have a simple hub that I am trying to write a test for with FakeItEasy and the verification of calling the client is not passing. I have the example working in a separate project that uses MOQ and XUnit.
public interface IScheduleHubClientContract
{
void UpdateToCheckedIn(string id);
}
public void UpdateToCheckedIn_Should_Broadcast_Id()
{
var hub = new ScheduleHub();
var clients = A.Fake<IHubCallerConnectionContext<dynamic>>();
var all = A.Fake<IScheduleHubClientContract>();
var id= "123456789";
hub.Clients = clients;
A.CallTo(() => all.UpdateToCheckedIn(A<string>.Ignored)).MustHaveHappened();
A.CallTo(() => clients.All).Returns(all);
hub.UpdateToCheckedIn(id);
}
I'm using Fixie as the Unit Test Framework and it reports:
FakeItEasy.ExpectationException:
Expected to find it once or more but no calls were made to the fake object.
The sample below works in XUnit & MOQ:
public interface IScheduleClientContract
{
void UpdateToCheckedIn(string id);
}
[Fact]
public void UpdateToCheckedIn_Should_Broadcast_Id()
{
var hub = new ScheduleHub();
var clients = new Mock<IHubCallerConnectionContext<dynamic>>();
var all = new Mock<IScheduleClientContract>();
hub.Clients = clients.Object;
all.Setup(m=>m.UpdateToCheckedIn(It.IsAny<string>())).Verifiable();
clients.Setup(m => m.All).Returns(all.Object);
hub.UpdateToCheckedIn("id");
all.VerifyAll();
}
I'm not sure what I've missed in the conversion?
You're doing some steps in a weird (it looks to me, without seeing the innards of your classes) order, and I believe that's the problem.
I think your key problem is that you're attempting to verify that all.UpdateToCheckedIn must have happened before even calling hub.UpdateToCheckedIn. (I don't know for sure that hub.UpdateToCheckedIn calls all.UpdateToCheckedIn, but it sounds reasonable.
There's another problem, where you configure clients.Setup to return all.Object, which happens after you assert the call to all.UpdateToCheckedIn. I'm not sure whether that's necessary or not, but thought I'd mention it.
The usual ordering is
arrange the fakes (and whatever else you need)
act, but exercising the system under test (hub)
assert that expected actions were taken on the fakes (or whatever other conditions you deem necessary for success)
I would have expected to see something more like
// Arrange the fakes
var all = A.Fake<IScheduleHubClientContract>();
var clients = A.Fake<IHubCallerConnectionContext<dynamic>>();
A.CallTo(() => clients.All).Returns(all); // if All has a getter, this could be clients.All = all
// … and arrange the system under test
var hub = new ScheduleHub();
hub.Clients = clients;
// Act, by exercising the system under test
var id = "123456789";
hub.UpdateToCheckedIn(id);
// Assert - verify that the expected calls were made to the Fakes
A.CallTo(() => all.UpdateToCheckedIn(A<string>.Ignored)).MustHaveHappened();

Is it a good practice to mock Automapper in unit tests?

There is this codebase where we use automapper and have 2 layers, Domain and Service. Each has its object for data representation, DomainItem and ServiceItem. The service gets data from domain, the uses constructor injected automapper instance to map
class Service
{
public ServiceItem Get(int id)
{
var domainItem = this.domain.Get(id);
return this.mapper.Map<DomainItem, ServiceItem>(domainItem);
}
}
Assume best practices, so mapper has no side-effects and no external dependencies. You'd write a static function to convert one object to another within seconds, just mapping fields.
With this in mind, is it a good practice to mock the mapper in unit tests like this?
[TestClass]
class UnitTests
{
[TestMethod]
public void Test()
{
var expected = new ServiceItem();
var mockDomain = new Mock<IDomain>();
// ... setup
var mockMapper = new Mock<IMapper>();
mockMapper.Setup(x => x.Map<DomainItem, ServiceItem>(It.IsAny<DomainItem>()))
.Returns(expected);
var service = new Service(mockDomain.Object, mockMapper.Object);
var result = service.Get(0);
Assert.AreEqual(expected, result);
}
}
To me, it seems that such unit test does not really bring any value, because it is effectively testing only the mocks, So i'd either not write it at all OR I'd use the actual mapper, not the mocked one. Am I right or do I overlook something?
I think the issue here is that the test is badly written for what it is actually trying to achieve which is testing Service.Get().
The way I would write this test is as follows:
[TestMethod]
public void Test()
{
var expected = new ServiceItem();
var mockDomain = new Mock<IDomain>();
var expectedDomainReturn = new DomainItem(0); //Illustrative purposes only
mockDomain.Setup(x => x.DomainCall(0)).Returns(expectedDomainReturn); //Illustrative purposes only
var mockMapper = new Mock<IMapper>();
mockMapper.Setup(x => x.Map<DomainItem, ServiceItem>(It.IsAny<DomainItem>()))
.Returns(expected);
var service = new Service(mockDomain.Object, mockMapper.Object);
var result = service.Get(0);
mockDomain.Verify(x => x.DomainCall(0), Times.Once);
mockMapper.Verify(x => x.Map<DomainItem, ServiceItem>(expectedDomainReturn), Times.Once);
}
This test instead of not really checking the functionality of the service.Get(), checks that the parameters passed are correct for the individual dependency calls based on the responses. You are thus not testing AutoMapper itself and should not need to.
Checking result is basically useless but will get the code coverage up.

DotCover shows 0% for virtual method mock

I'm using DotCover to check the unit test Coverage. Inside one of the method I return results from active directory in SearchResult however, I mocked the class but DotCover displays 0%
public virtual T SearchOneRecord(ISearchConfigurator configurator)
{
var record = (T)Activator.CreateInstance(typeof(T));
var searchResult = configurator.DirectorySearcher.FindOne();
if (searchResult != null)
{
AssignActiveDirectoryValue(searchResult, record);
}
return record;
}
[Test]
public void SearchOneRecord()
{
//Arrange
var configuratorMock = MockRepository.GenerateMock<ISearchConfigurator>();
var searchMock = MockRepository.GenerateStub<Searcher<NativeDs>>();
searchMock.Replay();
var nativeDs = new NativeDs() { PasswordAge = 100 };
searchMock.Expect(x => x.SearchOneRecord(configuratorMock)).Return(nativeDs);
//Act
var record = searchMock.SearchOneRecord(configuratorMock);
//Assert
Assert.AreEqual(nativeDs.PasswordAge, record.PasswordAge);
}
The test passes but since I'm new to RhinoMock (mocking in general) maybe there is an issue .
Any idea?
Correct me if I'm wrong but what you did here is defined mock and then tested if this mock works correctly? I don't think that's something you wanted to achieve. And of course it causes test to pass - mock is working correctly, but it is not testing you application code at all - hence 0% coverage.
What you want to do probably is to mock ISearchConfigurator instance and then pass that mock to method as a parameter.
[Test]
public void SearchOneRecord()
{
//Arrange
var configuratorMock = MockRepository.GenerateMock<ISearchConfigurator>();
var directorySearcherMock = MockRepository.GenerateMock<IDirectorySearcher>(); // please note I don't know exact type, so you need to ammend it
var returnValue = ... // initialize with types you expect DirectorySearcher to return
var searcher = new Searcher(); // initialize class you actually want to test
configurationMock.Replay();
configurationMock.Expect(x => x.DirectorySearcher).Return(directorySearcherMock);
directorySearcher.Expect(x => x.FindOne()).Return(returnValue);
searchMock.Expect(x => x.SearchOneRecord(configuratorMock)).Return(nativeDs);
//Act
var record = searcher.SearchOneRecord(configuratorMock);
//Assert
Assert.AreEqual(nativeDs.PasswordAge, record.PasswordAge);
}
Please note that I'm currently unable to test this code, but it should give you some directions into how it is supposed to be done.

.NET Unit Testing - Moq/xUnit frameworks with MVC, not returning expected results

Here's my scenario:
I'm working with a .NET MVC 4.0 project, with a repository (as you'd expect), and trying to implement the Moq/xUnit testing libraries into a .NET Unit Testing project.
I've got this far:
MVC Controller
private IHOLService _service;
public PolicyController(IHOLService service)
{
_service = service;
}
public ActionResult Index()
{
var policies = _service.GetAllPolicies(100, 0).ToList();
return View(policies);
}
Unit testing class
[Fact]
public void GetPolicies()
{
// Arrange
var mockService = new Mock<IHOLService>();
List<Policy> policy = new List<Policy>()
mockService.Setup(cr => cr.GetAllPolicies(10, 0)).Returns(policy);
var controller = new PolicyController(mockService.Object);
// policy here contains 0 results.
// Act
var result = (ViewResult)controller.Index();
var model = result.ViewData.Model; // equals 0.
// Assert
var listCategories = Assert.IsAssignableFrom<List<Policy>>(result.ViewData.Model);
// listCategories.Count equals 0 results.
Assert.Equal(10, listCategories.Count); // Thus always fails
}
My problem is that when the Controller is called directly, everything works fine, 100 policies are loaded.
However, when I run the test, 0 products are loaded, in which I'm guessing is a problem with the mocking calls somewhere down the line, potentially to do with the service initialisation. Has anyone ever had this before and can offer advice?
Also, am I correct to test my Service, rather than my Repository held at data layer?
Thanks in advance.
In your test code, you initialize policy to an empty list, then tell your mock service to return this empty list. To make the test load policies, you need to put some policy instances into your policy list.
I would write a test which looks something like this:
[Fact]
public void GetPolicies()
{
// Arrange
var mockService = new Mock<IHOLService>();
Policy expectedPolicy = new Policy(); // substitute for the real way you construct these
List<Policy> policy = new List<Policy>() { expectedPolicy };
mockService.Setup(cr => cr.GetAllPolicies(10, 0)).Returns(policy);
// Act
var result = (ViewResult)controller.Index();
var model = result.ViewData.Model; // equals 0.
// Assert
var listCategories = Assert.IsAssignableFrom<List<Policy>>(result.ViewData.Model);
Assert.Equal(expectedPolicy, listCategories.First());
}
But it really depends on what aspect of your code you are trying to unit test. From what I can see, this test simply confirms that you are storing the Policy objects as expected. You might write further tests for any logic that depends on the Policy instances themselves.

Categories

Resources