I am attempting to follow this example and leverage a shim to remove the external dependency on a WCF service call which is called from the method I am executing the unit test on. Unlike the example, I generate my WCF client on the fly using code similar to this:
ChannelFactory<IReportBroker> factory = new ChannelFactory<IReportBroker>("ReportBrokerBasicHttpStreamed", new EndpointAddress(this.CurrentSecurityZoneConfigurationManager.ConfigurationSettings[Constants.ConfigurationKeys.ReportBrokerServiceUrl]));
IReportBroker proxy = factory.CreateChannel();
proxy.Execute(requestMessage))
How do I adapt that example to shim the proxy returned back by the CreateChannel method? I am assuming that in the ShimWCFService class, I need to add something like....
ShimChannelFactory<TService>.AllInstances.CreateChannel = (var1) => { return [instance of a mock object]};
However, I am unsure of how to associate a mock object of <TService> with that shim as the return value.
You need to shim the factory for every type parameter. Assume you have the three Service contracts 'IService0' 'IService1' and 'IService2'.
Then you need to setup the shims like this:
ShimChannelFactory<IService0>.AllInstances.CreateChannel = (_) => { return new Service0Mock(); }
ShimChannelFactory<IService1>.AllInstances.CreateChannel = (_) => { return new Service1Mock(); }
ShimChannelFactory<IService2>.AllInstances.CreateChannel = (_) => { return new Service2Mock(); }
Related
I'm trying to write unit test for TranslateResponse().
private async Task TranslateResponse(Policy policy)
{
foreach(t in translatorFactory.BuildTranslator())
{
var policyTranslator=t as IPolicyAwareTranslator;
policyTranslator?.SetPolicy(policy);
}
}
The TranslateResponse() has many other translators though, but for now, I limited it to just one.
The BuildTranslator is as
public async Task<List<ITranslator>> BuildTranslators()
{
return new List<ITranslator>()
{
new PolicyTranslator()
}
}
Here I'm returning the PolicyTranslator which implements ITranslator and IPolicyAwareTranslator
ITranslator has Translate() while IPolicyAwareTranslator has SetPolicy(Policy policy) respectively.
Now that for Unit testing, I create a Mock of ITranslator and set it up and I create the Mock of IPolicyTranslator via As<>.
Mock<ITranslator> mockedTranslator=new Mock<ITranslator>();
mockedTranslator.Setup(t => t.Translate(_translatorDataAccessor.Object));
var mockedPolicyTranslator = mockedTranslator.As<IPolicyAwareTranslator>();
mockedPolicyTranslator.Setup(t => t.SetPolicy(It.IsAny<Policy>()));
List<ITranslator> translators = new List<ITranslator>(new List<ITranslator>() { mockedTranslator.Object });
translatorFactory.Setup(t => t.BuildTranslators(It.IsAny<string>())).ReturnsAsync(translators);
Still the verify call fails.
I'm I going in the right direction or missing something?
mockedPolicyTranslator.Verify(t => t.SetPolicy(new UnknownPolicy()), Times.AtLeastOnce);
The argument matcher will need to be loosened
mockedPolicyTranslator.Verify(t => t.SetPolicy(It.IsAny<UnknownPolicy>()), Times.AtLeastOnce);
since currently used new UnknownPolicy() instance wont match whatever is passed while testing
In attempts to do some test-driven-development, I've created the most basic, buildable method:
public class NoteService : INoteService
{
public IEnumerable<Annotation> GetNotes(ODataQueryOptions oDataQueryOptions)
{
return new List<Annotation>();
}
}
When trying to unit test it, it seems impossible to create an instance of ODataQueryOptions:
[TestFixture]
public class NoteServiceTests
{
[Test]
public void GetNotes_Returns_IEnumerable_Of_Notes()
{
var sut = new NoteService();
var queryOptions = new ODataQueryOptions(new ODataQueryContext(new EdmCoreModel(), new EdmCollectionType())// new new new etc??
Assert.That(() => sut.GetNotes(options), Is.InstanceOf<IEnumerable<Annotation>>());
}
}
How do you create a simple instance of the object ODataQueryOptions in order to inject it for unit tests?
Will this work?
var request = new HttpRequestMessage(HttpMethod.Get, "");
var context = new ODataQueryContext(EdmCoreModel.Instance, typeof(int));
var options = new ODataQueryOptions(context, request);
I wanted to do something similar and found a workable solution:
My use case
I have a web service that passes OData query parameters down to our CosmosDB document client which translates them into a CosmosDB SQL query.
I wanted a way to write integration tests directly on the CosmosDB client without having to make outgoing calls to other downstream services.
Approaches
Tried mocking ODataQueryParameters using Moq but because it's a class and not an interface, Moq can't properly instantiate all of the properties that I need
Tried instantiating one directly, but outside of an MVC application this is extremely difficult to build the required EdmModel.
Wondered if there is a way to do it without constructing an EdmModel?
I finally figured out a way to do it with the following:
This may not solve every use case, but here's the solution that I landed on for my needs:
public static class ODataQueryOptionsBuilder
{
private static WebApplicationFactory<TEntryPoint> _app =
new WebApplicationFactory<TEntryPoint>();
public static ODataQueryOptions<T> Build<T>(
string queryString)
where T : class
{
var httpContext = new DefaultHttpContext();
httpContext.Request.QueryString = new QueryString(queryString);
httpContext.RequestServices = _app.Services;
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntityType<T>();
var model = modelBuilder.GetEdmModel();
var context = new ODataQueryContext(
model,
typeof(T),
new Microsoft.AspNet.OData.Routing.ODataPath());
return new ODataQueryOptions<T>(context, httpContext.Request);
}
}
Conclusion
I realized that all I needed to get the ODataQueryOptions was a test server that was set up exactly like my web service. Once I realized that, the solution was simple. Use WebApplicationFactory to create the test server, and then allow OData to use the IServiceProvider from that application to build the ODataQueryOptions that I needed.
Drawbacks
Realize that this solution is as performant as your TEntryPoint, so if your application takes a long time to start up, this will cause unit/integration tests to take a long time to run.
I'm looking at the unit tests for SignalR and noticed one of the tests uses Moq to create a mock HubConnection:
[Fact]
public void HubCallbackClearedOnFailedInvocation()
{
var connection = new Mock<HubConnection>("http://foo");
var tcs = new TaskCompletionSource<object>();
tcs.TrySetCanceled();
connection.Setup(c => c.Send(It.IsAny<string>())).Returns(tcs.Task);
var hubProxy = new HubProxy(connection.Object, "foo");
var aggEx = Assert.Throws<AggregateException>(() => { hubProxy.Invoke("foo", "arg1").Wait(); });
var ex = aggEx.Unwrap();
Assert.IsType(typeof(TaskCanceledException), ex);
Assert.Equal(connection.Object._callbacks.Count, 0);
}
However, when I try and do the same with a slightly different mocking framework, RhinoMocks, it complains that the method isn't virtual:
[Test]
public void ShouldCreateBrokerWithHubConnection()
{
//Arrange
var url = "http://localhost6790";
var hubProxy = MockRepository.GenerateMock<IHubProxy>();
var hubConnection = MockRepository.GenerateMock<HubConnection>(url);
hubConnection.(c => c.CreateHubProxy("ArtemisClientHub")).Return(hubProxy);
... (more code)
}
System.InvalidOperationException : Invalid call, the last call has been used or no call has been made (make sure that you are calling a virtual (C#) / Overridable (VB) method).
Is this just a shortcoming of RhinoMocks compared to a newer library like Moq?
My tip is to use the none concrete types from your code and inject the concrete types using a Ioc. The signalr dot net client however is missing a DependencyResolver unlike the server. I rolled my own to get around this, you can check out the code here (But in your case you can use any Ioc like Ninject, autofac etc)
https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/blob/master/SignalR.EventAggregatorProxy.Client.DotNet/Bootstrap/DependencyResolver.cs
The hub connection and proxy is a bit hard to abstract since you are dependent on the concrete types to create the proxy. I solved it with abstracting the creation of the hub proxy to a factory interface that returns a IHubProxy that can be easily mocked.
Look here
https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/blob/master/SignalR.EventAggregatorProxy.Client.DotNet/Bootstrap/Factories/HubProxyFactory.cs
All examples are taken from my dot net client for this library
https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy
WCF makes it easy to call services synchronously or asynchronously, regardless of how the service is implemented. To accommodate clients using ChannelFactory, services can even define separate sync/async contract interfaces. For example:
public interface IFooService
{
int Bar();
}
[ServiceContract(Name = "IFooService")]
public interface IAsyncFooService
{
Task<int> BarAsync();
}
This allows the client to reference either contract version, and WCF translates the actual API calls automatically.
One drawback to providing both contract versions is that they must be kept in-sync. If you forget to update one, the client may receive a contract mismatch exception at runtime.
Is there an easy way to unit test the interfaces to ensure they match from a WCF metadata perspective?
You can retrieve the ContractDescription and use WsdlExporter to generate the WSDL. The output MetadataSet is XML serializable, so you can compare the representations for each contract version to ensure they match:
[TestMethod]
public void ContractsMatch()
{
// Arrange
string expectedWsdl = this.GetContractString<IFooService>();
// Act
string actualWsdl = this.GetContractString<IAsyncFooService>();
// Assert
Assert.AreEqual(expectedWsdl, actualWsdl);
}
private string GetContractString<TContract>()
{
ContractDescription description = ContractDescription.GetContract(typeof(TContract));
WsdlExporter wsdlExporter = new WsdlExporter();
wsdlExporter.ExportContract(description);
if (wsdlExporter.Errors.Any())
{
throw new InvalidOperationException(string.Format("Failed to export WSDL: {0}", string.Join(", ", wsdlExporter.Errors.Select(e => e.Message))));
}
MetadataSet wsdlMetadata = wsdlExporter.GetGeneratedMetadata();
string contractStr;
StringBuilder stringBuilder = new StringBuilder();
using (XmlWriter xmlWriter = XmlWriter.Create(stringBuilder))
{
wsdlMetadata.WriteTo(xmlWriter);
contractStr = stringBuilder.ToString();
}
return contractStr;
}
Your own answer is great. As BartoszKP points out it is more of an integration test, but this might be the best fit. You could argue that comparing two units (interfaces) to each other is not a unit test by definition.
The advantage of your approach is that you can be sure to verify what WCF makes from your classes. If you only want to test your own code, you could do something like that:
[TestMethod]
public void ContractsMatch()
{
var asyncMethodsTransformed = typeof(IAsyncFooService)
.GetMethods()
.Select(mi => new
{
ReturnType = mi.ReturnType,
Name = mi.Name,
Parameters = mi.GetParameters()
});
var syncMethodsTransformed = typeof(IFooService)
.GetMethods()
.Select(mi => new
{
ReturnType = WrapInTask(mi.ReturnType),
Name = Asyncify(mi.Name),
Parameters = mi.GetParameters()
});
Assert.That(asyncMethodsTransformed, Is.EquivalentTo(syncMethodsTransformed));
}
The idea is that for each method in your IFooService you expect a method which has a similar signature with clearly defined transformations:
The name must contain a "Async" after the "I"
The return type must be a Task of the type found in the sync version.
The WrapInTask and Asyncify are left as exercise :-) If you like this suggestion I can expand on them.
By using a test like that you might constrain the code more than WCF does (I don't know the Async support very well). But even if it does you might want that to ensure some code consistency.
I'm trying to create some unit tests for an application I've recently inherited. Currently using NSubstitute because that's what the previous programmer used, but I'm not attached to it.
The method I'm testing calls the DataService class' Create method.
Calling Create Method
var contactProductLink = this.dsService.Create<ContactProductLink>(x =>
{
x.ContactRoleId = prod.RoleId;
x.ContactId = contactViewModel.ContactId;
x.ProductId = prod.ProductId;
x.Active = true;
x.InsertDate = DateTime.Now;
x.InsertUserId = user.employeeId;
x.UpdateDate = DateTime.Now;
x.UpdateUserId = user.employeeId;
});
DataService Create Method:
public TEntity Create<TEntity>(Action<TEntity> propertySetter = null) where TEntity : class
{
var tEntity = this.Context.Create<TEntity>();
if (propertySetter != null)
{
propertySetter(tEntity);
}
return tEntity;
}
The approach I've taken (and maybe there's a better way) is to use NSubstitute to mock the DataService. When I'm doing my assertions at the end, I'm checking to make sure that the Create method was called:
mockDataSupplierService.Received().Create<ContactProductLink>(Arg.Any<Action<ContactProductLink>>());
However, I'd like to also verify the input that was sent to the method is correct, and here's where I'm running into trouble. I can get the System.Action object that was passed to the Create method, but I can't figure out how to pull out the parameters (such as ContactRoleId, ContactId, etc. as posted in the calling create method code snippet).
So after all of that what I'm asking is:
How can I access those input parameters so I can verify the correct arguments are being passed to the data service? Is it even possible?
Is there a better way to do this than what I'm currently trying to do?
Solution
//Arrange
mockDataSupplierService.Create<ContactProductLink>(Arg.Do<Action<ContactProductLink>>(x=> actionToPopulateEntity = x));
//Assert
mockDataSupplierService.Received().Create<ContactProductLink>(Arg.Any<Action<ContactProductLink>>());
var entity = new ContactProductLink();
actionToPopulateEntity.Invoke(entity);
Assert.AreEqual(ExpectedContactId, entity.ContactId);
How can I access those input parameters so I can verify the correct arguments are being passed to the data service? Is it even possible?
Essentially you can't, as it is not possible to extract "code" details from action (consider what happens when you pass an action that doesn't set any properties - this is totally legal, but would break hypothetical mechanism).
However, you can try this instead:
Create entity with initial values
Use Arg.Invoke argument, telling NSubstitute to use chosen object as action parameter
Verify that entity properties values changed
For example:
// Arrange
var entity = new ContactProductLink
{
ContactRoleId = // ...
// ...
};
mockDataSupplierService
.Create<ContactProductLink>(Arg<ContactProductLink>.Invoke(entity));
// Act
// ...
Assert.That(entity.ContactRoleId, Is.EqualTo(2));
// ...