How to mock Async Search? - c#

[Fact]
public async Task Test_GetCustomer_Status_When_No_Customer_Exist()
{
var customerEngine = A.Fake<ICustomerEngine>();
var monitorEngine = A.Fake<IMonitorEngine>();
var customerLog = A.Fake<ILogProvider<CustomerManager>>();
var conditions = new List<ScanCondition>();
var customers = new List<Customer>();
var names = new List<string>
{
"SERVICE"
};
var hashKey = "SITE";
A.CallTo(() => customerEngine.GetCustomers(conditions)).Returns(null); // Get customers returns AsyncSearch<Customer>
A.CallTo(() => monitorEngine.QueryItems(hashKey, QueryOperator.BeginsWith, names)).Returns(null);
CustomerManager manager = new CustomerManager(customerEngine, monitorEngine);
await manager.GetCustomers();
A.CallTo(() => customerEngine.GetCustomers(A<List<ScanCondition>>.Ignored)).MustHaveHappened();
}
Get customers returns AsyncSearch
But, How to mock AsyncSearch?
Is there any work around for this now?

I do not see the interface for this class hence it would be tough to fake it. I see this issue reported to AWS, if they come back with an fix in future, we can do it. There is work around as you will end up in doing lot of R&D. Refer this https://github.com/aws/aws-sdk-net/issues/772 and
https://github.com/aws/aws-sdk-net/issues/772

This is possible now as of version 3.7.4.9 of the AWSSDK.DynamoDBv2 package, as Norm Johanson mentions on the Github issue. You can mock AsyncSearch by creating your own subclass as he shows, or by using Moq like so:
var mockAsyncSearch = new Mock<AsyncSearch<YourClass>>();
mockAsyncSearch
.Setup(a => a.GetRemainingAsync(...))
.Returns(...);
And then your mocked IDynamoDbContext can just use .Returns(mockAsyncSearch.Object) as usual.

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.

XUnit how to mock IMemoryCache ASP.NET Core

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.

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.

how to assert mock state simultaneous with thrown exception

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.

Categories

Resources