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.
Related
I'm currently setting up some unit tests to return ID of the cafes using some mocking, but for some reason the result variable always returns null.
Setup in service class which implements the Get method
public async Task<CafeResponse> Get(int cafeId)
{
var cafe= await _cafeRepository.GetByIdAsync(cafeId);
return _mapper.Map<CafeResponse>(cafe);
}
Unit test setup: Currently the result variable shows null? Not sure if this is due to me setting up the mock incorrectly
[Fact]
public async Task Get_ShouldReturnCafeArray_WhenCafesInDatabase()
{
//Arrange
var cafeId = 98;
var cafeName = "bellas";
var cafeIdGuid = Guid.NewGuid();
var cafeDesc = "this is my test";
var cafeTypeId = 1;
var cafeDto = new Cafe
{
CafeId = cafeId,
Name = cafeName,
CafeGuid = cafeIdGuid,
Description = cafeDesc,
CafeTypeId = cafeTypeId,
};
var expected = new CafeResponse();
var mockCafe = new Mock<IRepositoryAsync<Cafe>>();
mockCafe.Setup(x => x.GetByIdAsync(cafeId)).ReturnsAsync(cafeDto);
var mockMapper = new Mock<IMapper>();
mockMapper.Setup(x => x.Map<Cafe, CafeResponse>(It.IsAny<Cafe>())).Returns(expected);
//Act
var cafeService = new CafeService(mockCafe.Object, mockMapper.Object);
var result = await cafeService.Get(cafeId); //always returns null
//Assert
mockCafe.Verify(x => x.GetByIdAsync(cafeId), Times.Once);
Assert.Equal(cafeId, result.CafeId);
}
The reason that you're getting a null result with the code that you have is because for IMapper you're mocking:
TDestination Map<TSource, TDestination>(TSource source);
but your actual code is using:
TDestination Map<TDestination>(object source);
So if you just want the test to return your "expected" instance of CafeResponse, then you need to update your Mock<IMapper> setup to be:
mockMapper.Setup(x => x.Map<CafeResponse>(It.IsAny<Cafe>())).Returns(expected);
The more appropriate solution as pointed out in the comments would be to simply create a Mapper instance for your test:
var mapper = new MapperConfiguration(cfg =>
{
cfg.AddProfile<MyProfile>();
}).CreateMapper();
Otherwise, you're just testing that you're mock is returning what you tell it to and not really verifying any functionality in your code.
I understand IMemoryCache.Set is an extension method so it can not be mocked. People have provided workarounds to such situation e.g as one by the NKosi here. I am wondering how I can achieve that for my data access layer where my MemoryCache returns a value and when not found it gets data from the db, set it to the MemoryCache and return the required value.
public string GetMessage(int code)
{
if(myMemoryCache.Get("Key") != null)
{
var messages= myMemoryCache.Get<IEnumerable<MyModel>>("Key");
return messages.Where(x => x.Code == code).FirstOrDefault().Message;
}
using (var connection = dbFactory.CreateConnection())
{
var cacheOptions = new MemoryCacheEntryOptions { SlidingExpiration = TimeSpan.FromHours(1) };
const string sql = #"SELECT Code, Message FROM MyTable";
var keyPairValueData = connection.Query<KeyPairValueData>(sql);
myMemoryCache.Set("Key", keyPairValueData, cacheOptions );
return keyPairValueData.Where(x => x.Code == code).FirstOrDefault().Message;
}
}
Following is my Unit Test - And off course it is not working as I can't mock IMemoryCache
[Fact]
public void GetMessage_ReturnsString()
{
//Arrange
// Inserting some data here to the InMemoryDB
var memoryCacheMock = new Mock<IMemoryCache>();
//Act
var result = new DataService(dbConnectionFactoryMock.Object, memoryCacheMock.Object).GetMessage(1000);
//assert xunit
Assert.Equal("Some message", result);
}
The first thing I would say is why not use a real memory cache? It would verify the behavior much better and there's no need to mock it:
// Arrange
var memCache = new MemoryCache("name", new NameValueCollection());
//Act
var result = new DataService(dbConnectionFactoryMock.Object, memCache).GetMessage(1000);
// Assert: has been added to cache
memCache.TryGetValue("Key", out var result2);
Assert.Equal("Some message", result2);
// Assert: value is returned
Assert.Equal("Some message", result);
If you really want to mock it out, here's a guide on how to do that:
Because it's an extension method, you need to make sure that it can be called as is. What happens in your case is that the extension method will call into the mock. Since you provide no expected behavior, it will probably fail.
You need to look at the code for the extension method, check what it accesses and then ensure that your mock complies with the expected behavior. The code is available here:
https://github.com/aspnet/Caching/blob/master/src/Microsoft.Extensions.Caching.Abstractions/MemoryCacheExtensions.cs#L77
This is the code:
public static TItem Set<TItem>(this IMemoryCache cache, object key, TItem value, MemoryCacheEntryOptions options)
{
using (var entry = cache.CreateEntry(key))
{
if (options != null)
{
entry.SetOptions(options);
}
entry.Value = value;
}
return value;
}
So, from that, you can see that it accesses CreateEntyand expects an object from it. Then it calls SetOptions and assigns Value on the entry.
You could mock it like this:
var entryMock = new Mock<ICacheEntry>();
memoryCacheMock.Setup(m => m.CreateEntry(It.IsAny<object>())
.Returns(entryMock.Object);
// maybe not needed
entryMock.Setup(e => e.SetOptions(It.IsAny<MemoryCacheEntryOptions>())
...
When you do this, the extension method will be called on the mock and it will return the mocked entry. You can modify the implementation and make it do whatever you want.
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();
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.
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.