I want to unit test my view model which makes wcf service calls.
My view model:
public class FooViewModel : Screen
{
private IService service;
public FooViewModel(IService service)
{
this.service = service;
}
public void Load()
{
service.LoadThisAndThat((o,e) =>
{
//Fill collections and so on
});
}
}
My service client interface:
public interface IService
{
void LoadThisAndThat(EventHandler<ThisAndThatCompletedArgs> callback);
}
This is implemented by a class which uses the actual generated service client proxy to make the call.
My question is: How can I unit test, that my view model does the service call and fills my collections with returned data?
To expand on Sheridan's answer - what are you trying to test?
The network connection?
The service frameworking (e.g. WCF)?
The .NET implementation of threads?
I'm guessing that all you are really interested in is how your view model responds to the data it is provided by the service. Let us slightly re-factor your code to make this more transparent (all we have really done it to remove the EventHandler delegate from the signature of the service method):
public class FooViewModel : Screen
{
private IService service;
public FooViewModel(IService service)
{
this.service = service;
}
public void Load()
{
Task.Factory.StartNew(() => service.GetResult())
.ContinueWith(t =>
{
//Fill collections and so on
});
}
}
public interface IService
{
Result GetResult();
}
Does this answer your question? No!
Even if you were to mock out the implementation of IService, the .NET implementation of threads does not guarantee anything about when the call to service.GetResult() will run, or when the results will be returned back to view model. However - are we interested in testing the .NET threading implementation? I guess not.
If you are dedicated to testing, then you have to consider the tests as first-class consumers of your code. To this end we have to modify our code to make it more amenable for testing. Take two is below:
public class FooViewModel : Screen
{
private IService service;
public FooViewModel(IService service)
{
this.service = service;
}
public void Load(bool runAync = true)
{
if (runAync)
Task.Factory.StartNew(() => service.GetResult())
.ContinueWith(t => SetResults(t.Result));
else SetResults(service.GetResult());
}
private void SetResults(Result result)
{
//Fill collections and so on
}
}
Here we have introduced a boolean parameter to the Load() method, which will default to true. During testing, we call it with false to ensure the results are dealt with synchronously and our view model is behaving as we would expect with the data returned.
If you don't like the addition of the extra parameter, you could just make the SetResults method public, and treat that as your initialization step during testing.
The takeaway is that we shouldn't be afraid to make changes to the public implementation to accommodate testing.
Simply implement a method that returns some data in your TestService class. The purpose is not to test whether the WCF service works, but to test how the view model works. As such, we create a situation which appears as if the service is working perfectly... we simply return the required data, but without needing to call the actual service which is one of the main things that we are trying to avoid.
the problem here is that the callback is called asynchronously.
the callback pattern is outdated, use Task !
you can do
public Task<int> Load()
{
TaskCompletionSource<int> source = new TaskCompletionSource<int>();
service.LoadThisAndThat((o,e) =>
{
//Fill collections and so on
source.SetResult(e.Count);
});
return source.Task;
}
so that in your test you could do (synchronously)
public void test()
{
var result=Load().Result;
}
Tasks are good for many many things !
Related
I am working on a web application that uses Angular 12 for the frontend and ASP.NET Core 6 for the backend. In our team we usually write just about anything as a 3-layer application (if possible) consisting of a presentation layer, a business logic layer and a data layer. In the case of this project, this would mean that when for example all entities of a certain type, let's call it Car, are requested from the server, the following would happen (simplified):
The request arrives in the CarController.cs controller. The carManager instance here belongs to the business layer and provides functions for interacting with car entities (CRUD for the most part). Dependency Injection is used to inject the carManager instance into the controller:
public async Task<ActionResult<List<Car>>> GetCars()
{
List<Car> cars = await this.carManager.GetCarsAsync();
return this.Ok(cars);
}
If there is anything business logic related, it will be done in the GetCarsAsync() function of the carManager. However, in many cases this is not necessary. Therefore, I often end up with "dumb" functions that just call the corresponding function of the data layer like this. The carAccessor in this example belongs to the data layer. Dependency Injection is also used here to inject its instance into the manager:
public async Task<ActionResult<List<Car>>> GetCarsAsync()
{
return this.carAccessor.GetCarsAsync();
}
The actual querying of the data is then done in the corresponding accessor for the entity. Example:
public async Task<List<Car>> GetCarsAsync()
{
List<Car> cars = new();
List<TblCar> dbCars = await this.Context.TblCars.ToListAsync();
foreach (TblCar dbCar in dbCars)
{
Car car = <AutoMapper instance>.Map<Car>(dbCar);
cars.Add(car);
}
return cars;
}
While this makes it easy to not mix up business logic and data access in the application, it really creates a whole lot of code that does nothing than just call other code. Therefore, in some cases the business layer is omitted simply because of laziness and business logic ends up just being implemented somewhere else, for example directly in the controller. Is there a simple solution for this?
Using generic base classes and inheritance could help you to reduce writing and maintaining of similar code everywhere for vanilla cases :
public abstract class BaseController<T, C>: Controller where T: class where C: IItemsManager<T>
{
protected C ItemManager { get; }
public virtual async Task<ActionResult<List<T>>> GetCars()
{
List<T> items = await this.ItemManager.GetItemsAsync();
return this.Ok(items);
}
}
public interface IItemsManager<T> where T : class
{
Task<List<T>> GetItemsAsync();
}
public class ItemsManager<T, B>: IItemsManager<T>
where T: class
where B: class
{
public virtual async Task<List<T>> GetItemsAsync()
{
List<T> items = new List<T>();
List<B> dbItems = await this.Context.Set<B>().ToListAsync();
foreach (B dbItem in dbItems)
{
T item = <AutoMapperinstance>.Map<T>(dbItem);
items.Add(item);
}
return items;
}
}
public class CarManager: ItemsManager<Car, TblCar>
{
}
public class CarController: BaseController<Car, CarManager>
{
}
In my current MVC application, I have architected a series of command objects to handle business actions. These business actions would be wrapped around service endpoints. These endpoints would also be consumed by an MVC frond-end & a windows app. Every business action will call into a DAO action, which in turn, calls into the required data access repositories to successfully perform the business action. I have listed an example action below.
Busines Action
public class CreateProjectAction
{
IInsertProjectDAOAction InsertProjectDAOAction { get; set; }
public void Execute()
{
// Does some business validation & other logic before
// calling the DAO action
InsertProjectDAOAction.Execute();
}
}
DAO Action
public interface IInsertProjectDAOAction
{
void Execute();
}
public class InsertProjectDAOAction
{
IProjectRepository ProjectRepository { get; set; }
public void Execute()
{
ProjectRepository.Insert();
}
}
Project Repository
public interface IProjectRepository
{
void Insert(Project proj);
// other db methods would be listed here
}
public class ProjectRepository
{
public void Insert(Project proj)
{
// Insert into the data store
}
}
Controller
[HttpPost]
public IHttpActionResult Create(NewProjectModel newProjectModel)
{
var cmdArgs = Mapper.Map<CreateProjectCommand.CreateProjectCommandArgs>(newProjectModel);
var action = new CreateProjectCommand(UserId, cmdArgs);
action.Execute();
if(action.IsSuccessful)
return Ok(project)
else
return InternalServerError(action.Exception);
}
Unit Test
public void InsertWith_ExistingProjectName_Returns_ServerError()
{
var arg = new CreateProjectCommandArgs(){ .... };
var cmd = CreateProjectAction(args);
action.Execute();
Assert.That(action.IsSuccessful, Is.False);
Assert.That(action.Exception, Is.TypeOf<UniqueNameExcepton>());
}
I am using Ninject to assist with the dependency injection between layers. I have a bunch of unit tests around the business 'CreateProjectAction' to test out expected behavior of that object. The business actions are wrapped around a series of Web API service endpoints. I would also like to write tests around my MVC controllers so that I can be sure they work as planned.
I like the architecure so far, but having trouble figuring out how to mock the DAO action properties in the business action when writing unit tests for the mvc controller. I'd love to hear suggestions, other viewpoints, etc ...
Your question is still a bit unclear. It seems likely for example that InsertProjectDAOAction implements the interface IInsertProjectDAOAction, even though your sample code doesn't indicate that it does. It's also unclear what CreateProjectCommand in your controller example is, since it isn't one of your example elements above it.
That said, one approach that you can take is to defer the creation of your commands out to a factory and inject the factory into your controller (through Ninject in your code and as a Mock in your unit tests). This allows you setup a mock chain. You mock the factory and have it return a mock of your action that you're interested in, which you can then setup to do whatever you want. At a very basic level, this might look like this:
public interface ICommandFactory {
IInsertProjectDAOAction CreateInsertProjectAction(int userId);
}
public class CommandFactory : ICommandFactory{
public IInsertProjectDAOAction CreateInsertProjectAction(int userId) {
return new InsertProjectDAOAction(/* userId???? */);
}
}
The controller would do something like this to use the factory:
public IHttpActionResult Create(/* ... */) {
var action = _commandFactory.CreateInsertProjectAction(1234);
action.Execute();
// ...
}
With a test looking something like:
[Test]
public void MyTest() {
var factoryMock = new Mock<ICommandFactory>();
var commandMock = new Mock<IInsertProjectDAOAction>();
factoryMock.Setup(x => x.CreateInsertProjectAction(It.IsAny<int>())).Returns(commandMock.Object);
commandMock.Setup(x => x.Execute()).Throws(new InvalidOperationException("Random failure"));
var controller = new MyController(factoryMock.Object);
try {
controller.Create(/* ... */);
Assert.Fail();
}
catch (InvalidOperationException ex) {
Assert.AreEqual("Random failure", ex.Message);
}
}
This is a general approach that you could take. However, as I've said, that might not be right for your situation, because your question is unclear. I've also ignored other issues about how you create / test your controller in general since that doesn't seem to be what your question is about...
I'm creating a class library API that wraps business logic and access to an SQL Server database via Entity Framework 6.
I've designed it using the Unit of work and repository patterns.
The purpose is to make it easy to use and to unit test.
Business logic and validation will be performed in the service layer.
I will not use an IOC container because I feel that it would complicate the API
usage.
The project have 15 repositories and services
The current design is as follows:
Service Layer A -> Unit of work -> Repository A and or B
Service Layer B -> Unit of work -> Repository B and or A...
...
public class ServiceA : IServiceA, IService
{
private readonly IUnitOfWork unitOfWork;
public AssetService(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
...
public IList<DomainObjectA> GetAll()
{
return unitOfWork.RepositoryA.GetAll();
}
public void Dispose()
{
unitOfWork.Dispose();
}
...
}
public class UnitOfWork : IUnitOfWork
{
private readonly MyDbContext context = new MyDbContext();
private IRepositoryA repositoryA;
private IRepositoryB repositoryB;
...
public IRepositoryA RepositoryA
{
get { return repositoryA = repositoryA ?? new RepositoryA(context); }
}
public IRepositoryB RepositoryB
{
get { return repositoryB = repositoryB ?? new RepositoryB(context); }
}
...
public void Save()
{
context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}
public class RepositoryA : Repository, IRepositoryA
{
public RepositoryA(MyDbContext context)
: base(context) {}
public IList<DomainObjectA> GetAll()
{
return context.tblA.ToList().Select(x => x.ToDomainObject()).ToList();
}
...
}
Since this is an API that should be used by other projects, I need a nice and "fairly" easy to use interface for the user that consumes the API.
Because of this the UnitOfWork is created in this "public interface" between the user and the service layer, see below.
I also think it's best that the using-statement lies within the API so that the db-context is disposed properly and immediately after each service call.
I started out using the Proxy pattern for this:
Example:
public class ProxyA : Proxy, IServiceA
{
public IList<DomainObjectA> GetAll()
{
using (var service = GetService<ServiceA>())
return service.GetAll();
}
...
}
public abstract class Proxy
{
protected T GetService<T>() where T : IService
{
return (T)Activator.CreateInstance(typeof(T), new object[] { new UnitOfWork()});
}
}
But this would require me to create a proxy for each service. I could of course skip the service interface in the proxy and create a common proxy which handles all the services.
I've also looked at the Facade pattern but can't decide which pattern to use for this particular scenario.
My questions:
Is this a good approach or are there any other design patterns that will solve this problem?
Also, should there be one public API entry point or several, grouped by some business logic?
I see nothing wrong with your design and the patterns you use.
Regarding the proxy pattern it is your call if you want to use it or not. As you mention you have to create boiler plate code to create one for every service. If it is arguable if you want to use it only to hide the call to the db service, or you prefer to add that line of code every time you call the service (and make sure you do it to avoid leaks). Also you may consider if you may need to add extra functionality in the Proxy in the future, which will put extra weight to create the proxy option.
Regarding a single entry point or several, I would create a ServiceA, ServiceB, ServiceC etc (so several) grouped for business logic domains. Typically you'll have between 5-20 (just an approximate number to give an idea of the magnitude)
You may want to review the interface segregation principle which supports this idea
http://en.wikipedia.org/wiki/Interface_segregation_principle
I'm struggling to find a way forward here.
I have a VB6 screen, which i need to call a .Net 'adapter' component, which calls out to a WCF service.
The WCF service is under windows authentication as i want to detect the windows logon of the user calling the functionality.
The service reference is in the .Net adapter. To get this to work i have had to add detail to a binding, specifying the security, which all works fine in the real world.
My problem is unit testing this, and trying to mock the call to the WCFServiceClient. Because i am using a parametrised constructor, Moq will not mock it. So i believe that my mock is therefore not being used, and a real call is going through to the WCF layer when i run my unit test (it is, i put a break point in the wcf service running locally in my solution).
To simplify my code i've pasted a BasicHttpBinding in, as the problem isnt the security, its how do i recode the function so i can mock the call, or can i do something else allowing me to mock the call?
In the .Net adapter, in the function i am calling i have the following code
using (var myWcfService = new MyWcfServiceClient(new BasicHttpBinding (), GetEndpointAddress()))
{
//do stuff here
}
In my unit test i have the following mock setup
var mockMyWcfService = new Mock<IMyWcfService>();
Which is not creating a mock that gets used by the above code.
If i put parameter types into the constructor, that does not work either as Moq will only mock an interface, and a default empty constructor (i believe , from googling my previous error)
Also, although in other projects in the solution we use Unity for IOC, i do not believe i can do that in this project as the .Net adapter is called from a VB6 app, which has no app.config for me to specify all of the unity config.
Thanks
If I understand it correctly, you have a class that uses a MyWcfServiceClient() and you want to control it's lifetime within your class (ergo the using block) therefore you cannot pass in a mocked service.
e.g.
public interface IMyWcfService {
void DoSomething();
}
public class MyClass {
private readonly IMyWcfService myService;
public MyClass(IMyWcfService myService) {
this.myService = myService;
}
public void DoIt() {
myService.DoSomething();
}
}
What you can try is to use a provider to create the service and pass this in and use a default provider to generate the service when not unit testing.
e.g.
public interface IService : IDisposable {
}
public class DefaultService : IService {
public void Dispose() {
}
}
public interface IServiceProvider {
IService GetService();
}
public class DefaultServiceProvider : IServiceProvider {
public IService GetService() {
return new DefaultService();
}
}
public class Consumer {
private readonly IServiceProvider serviceProvider;
public Consumer() : this (new DefaultServiceProvider()){
}
internal Consumer(IServiceProvider serviceProvider) {
this.serviceProvider = serviceProvider;
}
public void DoIt() {
using (var service = serviceProvider.GetService()) {
// do stuff
}
}
}
I generally make the unit test constructors internal - personal preference, not required.
In the unit test you can create a mock provider that returns a mock service.
Do I have to rewrite my code to do this into an interface? Or is there an easier way? I am using Moq
What I usually do is build a wrapper or an adapter around my web service and just mock that.
for instance:
public class ServiceAdapter: IServiceAdapter
{
public void CallSomeWebMethod()
{
var someService = new MyWebService();
someService.SomeWebMethod();
}
}
Then I just stub the service adapter.
[Test]
public void SomeMethod_Scenario_ExpectedResult()
{
var adapterMock = new Mock<IServiceAdapter>();
//do your test
}
been writing a couple of responses about unit testing and mocking lately. I wrote elsewhere that it's important to ask yourself what exactly are you testing. Regarding your particular situation, I would hope the answer is "I am testing the business logic my WebService is exposing", and not "I am testing my WebService" - there's a difference.
If your concerns are server-side
You do not need to test WebServices in general. MS has already done that. Millions of people have done that. Testing the transport layer, the protocol, the definition of WebServices is a waste of time.
You need to target your business logic. The best way to do this is to separate your business logic from your WebService. Consider the following
public class MyWebSevice : System.Web.Services.WebService
{
private AuthenticationService _auth = new AuthenticationService ();
private int _count = 0;
[WebMethod]
public string DoSomething ()
{
// embedded business logic, bad bad bad
if (_auth.Authenticate ())
{
_count++;
}
return count.ToString ();
}
}
there is no way to test that logic without invoking the WebService directly. What you really want is
public class MyService
{
// keeners will realise this too should be injected
// as a dependency, but just cut and pasted to demonstrate
// isolation
private AuthenticationService _auth = new AuthenticationService ();
private int _count = 0;
public string DoSomething ()
{
if (_auth.Authenticate ())
{
_count++;
}
return count.ToString ();
}
}
in prod
// this web service is now a consumer of a business class,
// no embedded logic, so does not require direct testing
public class MyWebSevice : System.Web.Services.WebService
{
private readonly MyService _service = new MyService ();
[WebMethod]
public string DoSomething ()
{
_service.DoSomething ();
}
}
in test
// test business logic without web service! yay!
[Test]
public void Test_DoSomething ()
{
MyService service = new MyService ();
string actual = service.DoSomething ();
// verify results
}
managing dependencies [like the AuthenticationService member] is a separate issue. However, making your WebMethods simple passthroughs to proper underlying business classes and removing logic from them completely, allows you to target "real" user code as opposed to the plumbing of your typical WebService implementation.
If your concerns are client-side
You have a business component calling a webservice, and I agree that you don't want to create a client for unit testing.
public partial class MyWebService :
System.Web.Services.Protocols.SoapHttpClientProtocol
{
...
public string DoSomething () { ... }
}
public class MyClient
{
public void CallService ()
{
MyWebService client = new MyWebService ();
client.DoSomething ();
}
}
Here, you have dependency issues, namely you cannot test MyClient.CallService without instantiating and hosting your WebService. Especially disconcerting if you do not own or host said remote service. In this case, yes, you should write against an interface - once again to separate and isolate business logic.
public interface IMyWebService
{
string DoSomething ();
}
public class MyWebServiceWrapper : IMyWebService
{
public string DoSomething ()
{
MyWebService client = new MyWebService ();
client.DoSomething ();
}
}
public class MyClient
{
private readonly IMyWebService _client = null;
public MyClient () : this (new MyWebServiceWrapper ()) { }
public MyClient (IMyWebService client)
{
_client = client;
}
public void CallService ()
{
_client.DoSomething ();
}
}
in test
[Test]
public void Test_CallService ()
{
IMyWebService mockService = null;
// instantiate mock with expectations
MyClient client = new MyClient (mockService);
client.CallService ();
// verify results
}
In general, if a class's dependencies are in-proc services, the decision to apply a pattern like Dependency Injection [DI] or Inversion of Control [IoC] is up to you - and your desire to isolate and unit test these services will inform your design. However, if a class's dependencies cross a process boundary, eg Database or WebService, I highly recommend applying these patterns as we did above.
Really, it's just plain old interface development. You probably already see how it pays off.
:)
I blogged about this a long time ago. Basically using partial classes and a bit of effort (either automated or manual, depending on how often you're going to change the web service) you can make the web service proxy class implement an interface. You can then mock it as normal.
there is an easy way.
for example if we have WebService class with the name DbService,
first create an interface for it (ex. IService), and use this interface for mocking, then add a class to your project and put this:
public partial class DbService:IService {
}
leave class empty, because of web services are partial class we use this implementation.
(previously