My problem is NOT trying to simply verify whether a method was called or not. Instead, I have a method that works on a collection of objects and I want to verify that a method on all of the collection items is being called.
Use the example of a plug-in model where I have a plug-in manager that contains a collection of plug-in objects. Each plug-in subclasses the PlugIn abstract base class which exposes an abstract Initialize method. In my test I want to make sure that Initialize is called on every plug-in regardless of whether one of them throws an exception (just part of a larger test suite).
My initial approach was to create a collection of mocked plug-ins, then configure the class under test (PlugInManager) to use the mocked objects. I then perform the test by calling PlugInManager.DoWork() which should iterate through the collection, calling DoWork() on each item.
The full test codes is as follows:
[TestMethod()]
public void MyTest()
{
// ARRANGE
var testParameter = new Something();
var mockPlugIns = new Collection<Mock<PlugIn>>()
{
new Mock<PlugIn>(),
new Mock<PlugIn>(),
new Mock<PlugIn>()
};
var plugIns = new Collection<PlugIn>();
foreach (var plugIn in mockPlugIns)
plugIns.Add(plugIn.Object);
var testManager = new PlugInManager()
{
PlugIns = plugIns
};
// ACT
testManager.DoWork(testParameter);
// ASSERT
foreach (var mockPlugIn in mockPlugIns)
mockPlugIn.Verify(plugin => plugin.DoWork(testParameter), Times.Once());
// Also tried using It.IsAny<Something>()
}
public abstract class PlugIn
{
abstract void DoWork(Something something);
}
public sealed class PlugInManager
{
public IEnumerable<PlugIn> PlugIns { get; set; }
public void DoWork(Something something)
{
foreach (var plugIn in PlugIns)
plugIn.DoWork(something);
}
}
Unfortunately, Verify fails for every item.
I've stepped through the code and see that it actually is working correctly and the Initialize method is being called on every item. When, then, is Verify failing???
UPDATE #1
I've updated the post to show the entire test method in one block. I've also changed the method to require a parameter as is the case in my real code (now).
UPDATE #2
The error I receive when running the test is:
Moq.MockException:
Expected invocation on the mock once, but was 0 times: plugin => plugin.DoWork(It.IsAny<Something>())
No setups configured.
No invocations performed.
As mentioned, when I step through the unit test I see that each of the plugins are actually being called. For some reason, however, Moq doesn't seem to be registering it or recognizing it.
UPDATE #3
After playing with the test code more, I discovered that I could make the test pass with a simple change. The test passes if I replace the foreach loop in the middle of the method with the following:
plugIns.Add(mockPlugIns[0]);
plugIns.Add(mockPlugIns[1]);
plugIns.Add(mockPlugIns[2]);
I don't see how this is making a difference and would ultimately like to make the number of items dynamic so the tests aren't always testing the case when there are three, so using the foreach is really what I need.
Any ideas?
This is actually not true and upon further testing this morning, I find that everything is working fine with the original foreach loop. I have no idea what changed but I tried many different variations late last night and while the code I have this morning looks just like what is posted, for whatever reason, the test is now passing!?!?!?!?
This worked for me in LINQPad with Moq 4. The only thing I changed was adding the parentheses on Times.Once().
void Main()
{
var MockPlugIns = new Collection<Mock<PlugIn>>()
{
new Mock<PlugIn>(),
new Mock<PlugIn>(),
new Mock<PlugIn>()
};
var plugIns = new Collection<PlugIn>();
foreach (var mockPlugIn in MockPlugIns)
plugIns.Add(mockPlugIn.Object);
var testManager = new PlugInManager()
{
PlugIns = plugIns
};
testManager.Initialize();
foreach (var mockPlugIn in MockPlugIns)
mockPlugIn.Verify(plugin => plugin.Initialize(), Times.Once());
}
public abstract class PlugIn
{
public abstract void Initialize();
}
public class PlugInManager
{
public void Initialize()
{
foreach (var plugIn in PlugIns)
{
plugIn.Initialize();
}
}
public Collection<PlugIn> PlugIns { get; set; }
}
UPDATE
I ran your updated test code, and it passed given the following implementation:
public class PlugInManager
{
public void DoWork(Something s)
{
foreach (var plugIn in PlugIns)
{
plugIn.DoWork(s);
}
}
public Collection<PlugIn> PlugIns { get; set; }
}
It passed with or without the It.IsAny change you mentioned. One initial thought was that you might not have been passing the same instance of Something to the plug-ins, but It.IsAny would have resolved that.
In short, it appears that you are doing everything right in the tests. Perhaps the issue is in the actual implementation.
Please post your implementation of PlugInManager.DoWork and the exact error message you get when the test fails. Also, what version of Moq are you using?
UPDATE
I cut-and-pasted your code and tried it. I had to make one change: abstract void DoWork on abstract class PlugIn needs to be public. After making that change it compiles and the test passes. If I comment out the "ACT" portion of your test, it fails with the error message you saw (as I would expect).
Something is different in your project or environment. I'm running .NET 4 (not Mono) under Windows 64 with Moq 4.0. Everything you have posted is correct. I would suggest confirming that you're running the latest binary of Moq, checking your project references, and trying some very simple verification tests to insure that Moq is working.
Related
We are transitioning from Xamarin.Forms to .Net MAUI but our project uses Prism.Unity.Forms. We have a lot of code that basically uses the IContainer.Resolve() passing in a collection of ParameterOverrides with some primitives but some are interfaces/objects. The T we are resolving is usually a registered View which may or may not be the correct way of doing this but it's what I'm working with and we are doing it in backend code (sometimes a service). What is the correct way of doing this Unity thing in DryIoC? Note these parameters are being set at runtime and may only be part of the parameters a constructor takes in (some may be from already registered dependencies).
Example of the scenario:
//Called from service into custom resolver method
var parameterOverrides = new[]
{
new ParameterOverride("productID", 8675309),
new ParameterOverride("objectWithData", IObjectWithData)
};
//Custom resolver method example
var resolverOverrides = new List<ResolverOverride>();
foreach(var parameterOverride in parameterOverrides)
{
resolverOverrides.Add(parameterOverride);
}
return _container.Resolve<T>(resolverOverrides.ToArray());
You've found out why you don't use the container outside of the resolution root. I recommend not trying to replicate this error with another container but rather fixing it - use handcoded factories:
internal class SomeFactory : IProductViewFactory
{
public SomeFactory( IService dependency )
{
_dependency = dependency ?? throw new ArgumentNullException( nameof(dependency) );
}
#region IProductViewFactory
public IProductView Create( int productID, IObjectWithData objectWithData ) => new SomeProduct( productID, objectWithData, _dependency );
#endregion
#region private
private readonly IService _dependency;
#endregion
}
See this, too:
For dependencies that are independent of the instance you're creating, inject them into the factory and store them until needed.
For dependencies that are independent of the context of creation but need to be recreated for each created instance, inject factories into the factory and store them.
For dependencies that are dependent on the context of creation, pass them into the Create method of the factory.
Also, be aware of potential subtle differences in container behaviours: Unity's ResolverOverride works for the whole call to resolve, i.e. they override parameters of dependencies, too, whatever happens to match by name. This could very well be handled very differently by DryIOC.
First, I would agree with the #haukinger answer to rethink how do you pass the runtime information into the services. The most transparent and simple way in my opinion is by passing it via parameters into the consuming methods.
Second, here is a complete example in DryIoc to solve it head-on + the live code to play with.
using System;
using DryIoc;
public class Program
{
record ParameterOverride(string Name, object Value);
record Product(int productID);
public static void Main()
{
// get container somehow,
// if you don't have an access to it directly then you may resolve it from your service provider
IContainer c = new Container();
c.Register<Product>();
var parameterOverrides = new[]
{
new ParameterOverride("productID", 8675309),
new ParameterOverride("objectWithData", "blah"),
};
var parameterRules = Parameters.Of;
foreach (var po in parameterOverrides)
{
parameterRules = parameterRules.Details((_, x) => x.Name.Equals(po.Name) ? ServiceDetails.Of(po.Value) : null);
}
c = c.With(rules => rules.With(parameters: parameterRules));
var s = c.Resolve<Product>();
Console.WriteLine(s.productID);
}
}
I'm new to ASP.NET and I'm refactoring some functionalities in my MVC-structured ASP.NET application into area's. This has already lead to controller-methods not able to find their views anymore, which results in the following page:
To test if all controllers can find their views, I'd like to write some automated unit tests for this.
I have came up with the following:
[TestMethod]
public void AboutTest()
{
var controller = new HomeController();
var result = controller.About() as ViewResult;
Assert.IsNotNull(result);
}
which tests the About-method in the following code:
public class HomeController : Controller
{
public ActionResult About()
{
return View();
}
public ActionResult Contact()
{
return View("~/Views/SomeFolder/Contact.cshtml");
}
}
But even when the HomeControllers About-method can not find a view, this assert succeeds, so this does not work for me.
I have found a solution online to use use ViewEngine.FindView() here. I don't think I can use this, since in some controllers the views are referenced by a hardcoded string (see the contact method in the example controller above) instead of just returning the default view (simularly named as its method). The ViewEngine.FindView(controller.ControllerContext, "about", "about"); will then fail, but the controller-method would not.
Another solution states to use Assert.IsEqual() and check if the result.ViewName is equal to a hardcoded string (for example: "About"). Since I do not set or know the title of the views I'm expecting to get returned, this would not be a solution either.
(How) would I be able to test my application for this?
You shouldn't check for null, it will return a ViewResult even when it doesn't render.
To test whether it actually renders use AssertViewRendered from mvccontrib.
[TestMethod]
public void AboutTest()
{
var controller = new HomeController();
var result = controller.About().AssertViewRendered();
}
You can even check for a specific view like so:
result.AssertViewRendered().ForView(MVC.Your.Views.AboutView);
Or supply data like so:
controller.page().AssertViewRendered().ForView("page").WithViewData<SomeModel>();
For an interactive tutorial with lots of pictures I can recommend: http://toreaurstad.blogspot.nl/2011/09/adventures-with-mvccontrib-testhelper.html
Edit:
You might also check out Selenium to test your entire app (incl. rendering of 200 routes).
How can I dispose and re-instantiate a singleton with Prism/DryIoC in Xamarin Forms?
I'm working with Azure Mobile Apps for offline data. Occasionally, I need to delete the local sqlite database and re-initialize it. Unfortunately the MobileServiceClient occasionally holds the db connection open and there's no method exposed to close it. The suggested solution (https://github.com/Azure/azure-mobile-apps-net-client/issues/379) is to dispose of MobileServiceClient. Only problem is that is registered with DryIoC as a singleton.
I'm not overly familiar with DryIoC, or Prism and Forms for that matter... But for the life of me, I can't see a way to do this.
I did cook up a pretty elaborate scheme that almost worked.
In my ViewModel method, when I needed the db freed up, I fired off an event -
_eventAggregator.GetEvent<RegisterDatabaseEvent>().Publish(false);
Then in App.xaml.cs, I wired up a listener and a handler like so -
_eventAggregator.GetEvent<RegisterDatabaseEvent>().Subscribe(OnRegisterDatabaseEventPublished);
private void OnRegisterDatabaseEventPublished()
{
Container.GetContainer().Unregister<IAppMobileClient>();
Container.GetContainer().Unregister<IMobileServiceClient>();
Container.GetContainer().Register<IMobileServiceClient, AppMobileClient>(new SingletonReuse());
Container.GetContainer().Register<IAppMobileClient, AppMobileClient>(new SingletonReuse());
_eventAggregator.GetEvent<RegisterDatabaseCompletedEvent>().Publish(register);
}
Lastly, back in the ViewModel constructor, I had a final listener that handled the event coming back from App.xaml and finished processing.
_eventAggregator.GetEvent<RegisterDatabaseCompletedEvent>().Subscribe(OnRegisterDatabaseCompletedEventPublished);
So the amazing thing is that this worked. The database was able to be deleted and all was good. But then I navigated to a different page and BOOM. DryIoC said it couldn't wire up the ViewModel for that page. I assume the unregister/register jacked up DryIoC for all injection... So how can I accomplish what needs to be done?
FINAL SOLUTION
Thanks so much to dadhi for taking the time to help. You are certainly a class act and I'm now considering using DryIoC elsewhere.
For anyone who stumbles on this, I'm posting the final solution below. I'll be as verbose as I can to avoid any confusion.
First, in my App.xaml.cs, I added a method for registering my database.
public void RegisterDatabase(IContainer container)
{
container.RegisterMany<AppMobileClient>(Reuse.Singleton,
setup: Setup.With(asResolutionCall: true),
ifAlreadyRegistered: IfAlreadyRegistered.Replace,
serviceTypeCondition: type =>
type == typeof(IMobileServiceClient) || type == typeof(IAppMobileClient));
}
I simply add a call to that method in RegisterTypes in place of registering the types in there directly.
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.GetContainer().Rules.WithoutEagerCachingSingletonForFasterAccess();
...
RegisterDatabase(containerRegistry.GetContainer());
...
}
Note also the added rule for eager caching, per dadhi.
Later on when I need to release the database in the ViewModel... I kick things off by resetting my local db variable and sending an event to App.xaml.cs
_client = null;
_eventAggregator.GetEvent<RegisterDatabaseEvent>().Publish(true);
In App.xaml.cs, I have subscribed to that event and tied it to the following method.
private void OnRegisterDatabaseEventPublished()
{
RegisterDatabase(Container.GetContainer());
_eventAggregator.GetEvent<RegisterDatabaseCompletedEvent>().Publish(register);
}
Here I just call RegisterMany again, exactly the same as I do when the app starts up. No need to unregister anything. With the setup and ifAlreadyRegistered arguments (thanks, dadhi!), DryIoC allows the object to be replaced. Then I raise an event back to the VM letting it know the database has been released.
Finally, back in the ViewModel, I'm listening for the completed event. The handler for that event updates the local copy of the object like so.
_client = ((PrismApplication)App.Current).Container.Resolve<IAppMobileClient>();
And then I can work with the new object, as needed. This is key. Without setting _client to null above and resolving it again here, I actually ended up with 2 copies of the object and calls to methods were being hit 2x.
Hope that helps someone else looking to release their Azure Mobile Apps database!
I am not sure how exactly XF handles these things.
But in DryIoc in order for service to be fully deleted or replaced it need to be registered with setup: Setup.With(asResolutionCall: true). Read here for more details: https://bitbucket.org/dadhi/dryioc/wiki/UnregisterAndResolutionCache#markdown-header-unregister-and-resolution-cache
Update
Here are two options and considerations that work in pure DryIoc and may not work XF. But it probably may help with solution.
public class Foo
{
public IBar Bar { get; private set; }
public Foo(IBar bar) { Bar = bar; }
}
public interface IBar {}
public class Bar : IBar {}
public class Bar2 : IBar { }
[Test]
public void Replace_singleton_dependency_with_asResolutionCall()
{
var c = new Container(rules => rules.WithoutEagerCachingSingletonForFasterAccess());
c.Register<Foo>();
//c.Register<Foo>(Reuse.Singleton); // !!! If the consumer of replaced dependency is singleton, it won't work
// cause the consumer singleton should be replaced too
c.Register<IBar, Bar>(Reuse.Singleton,
setup: Setup.With(asResolutionCall: true)); // required
var foo = c.Resolve<Foo>();
Assert.IsInstanceOf<Bar>(foo.Bar);
c.Register<IBar, Bar2>(Reuse.Singleton,
setup: Setup.With(asResolutionCall: true), // required
ifAlreadyRegistered: IfAlreadyRegistered.Replace); // required
var foo2 = c.Resolve<Foo>();
Assert.IsInstanceOf<Bar2>(foo2.Bar);
}
[Test]
public void Replace_singleton_dependency_with_UseInstance()
{
var c = new Container();
c.Register<Foo>();
//c.Register<Foo>(Reuse.Singleton); // !!! If the consumer of replaced dependency is singleton, it won't work
// cause the consumer singleton should be replaced too
c.UseInstance<IBar>(new Bar());
var foo = c.Resolve<Foo>();
Assert.IsInstanceOf<Bar>(foo.Bar);
c.UseInstance<IBar>(new Bar2());
var foo2 = c.Resolve<Foo>();
Assert.IsInstanceOf<Bar2>(foo2.Bar);
}
I want to write unit test for a class that contains linq to sql codes . I mean inside each method I have created a new DbContext and done database jobs .
I searched the web . first I came to use repository and Unit of Work patterns but I figured out that DbContext itself is a unit of work and its dbset works as repositories . another point is that I think there is no need to test Linq part because it works as it should ( tested by .net team ) . I want to test the logic I have added to the code . so I decided to create an interface with necessary methods with two implementations , one uses linqToSql while another is just a mock . something like this :
public interface IDbManager
{
bool Insert(MyEntity newEntity);
}
public class RealDbManager:IDbManager
{
public bool Insert(MyEntity newEntity)
{
using (DbDataContext db = new DbDataContext())
{
db.MyEntities.InsertOnSubmit(newEntity);
db.SubmitChanges();
}
}
}
public class MockDbManager:IDbManager
{
public bool Insert(MyEntity newEntity)
{
return true;
}
}
is the whole idea correct ? if so is this a correct implementation ?
is it possible to define DbDataContext as a class variable instead of creating new instance inside each method ?
You have the right general idea for a start. Your Mock Insert method should save the entity to some in-memory store so that subsequent queries will return the inserted information, as would be expected. But the very basic idea of having an interface, with a 'real' and a 'mock' implementation is there.
Remember that when using your Mock in tests, you are testing your other code that uses the mock - not the mock itself.
As for defining the DataContext as a member variable; you could use an IDisposable pattern for it, like so:
public class RealDbManager:IDbManager, IDisposable
{
DbDataContext db = new DbDataContext();
public bool Insert(MyEntity newEntity)
{
{
db.MyEntities.InsertOnSubmit(newEntity);
db.SubmitChanges();
}
}
public void Dispose()
{
db.Dispose();
}
}
You would just have to be sure to dispose of your DbManager, then.
Yes. The only thing I would avoid is to create an actual mocked class (in this case it should be called Fake), but using a mocking engine.
In your question you mention two kind of tests. First is testing the behavior of your class, the second is testing the integration of it. They seem the same but it's not.
In the first you need to mock your class to test its 'connection' against your other classes this way (using Moq):
[Test]
public void Test()
{
var entity = new Entity();
var mocked = new Mock<IDbManager>();
//you are telling the moq engine everytimes it finds an invocation of your repository
//to return true as you did in you mocked class
mocked.Setup( x => x.Insert( entity ) ).Returns( true );
var classUnderTest = new ClassUnderTest( mocked.Object );
//in this method you invoke your repository
var ret = classUnderTest.DoSomething( entity );
//assertions
Assert.Equal( something, ret);
//eventually you can verify that your repository has been hit once
mocked.Verify( x => x.Insert( It.IsAny<Entity>), Times.Once);
}
in the later as you correctly state, you have nothing to test on linq (Microsoft did it for us), but in case you need to verify the correctness of your linq you can do it only against a real db (or using a repository pattern against a fake repository). This is an integration test and it's has nothing to share with mocking.
To decouple your class from DbContext you could use repository pattern. Have a look at this article. http://dotnetspeak.com/index.php/2011/03/repository-pattern-with-entity-framework/
I have an ASP.NET website project that until recent had all code in App_Code folder. It uses Entity Framework 4 as ORM. Application is divided into three "sections" (let's say one for each customer). Each section has it's own database (but same schema). This is due to performance reasons, databases are over 10GB each with millions of rows.
Each time a context object is created a Session variable which holds section ID is called and proprietary connection string is chosen for this context.
It looks like this (following are members of static Connection class):
public static MyEntities GetEntityContext()
{
if (HttpContext.Current.Session["section"] == null)
{
HttpContext.Current.Response.Redirect("~/Login.aspx");
}
var context = new MyEntities(GetEntityConnectionStringForSection((int)HttpContext.Current.Session["section"]);
return context;
}
private static string GetEntityConnectionStringForSection(int section)
{
switch (section)
{
case 1: return ConfigurationManager.ConnectionStrings["entity_1"].ConnectionString;
case 2: return ConfigurationManager.ConnectionStrings["entity_2"].ConnectionString;
case 3: return ConfigurationManager.ConnectionStrings["entity_3"].ConnectionString;
default: return ConfigurationManager.ConnectionStrings["entity_1"].ConnectionString;
}
}
It works very good and also handles situation when session timed out everytime any data access is performed.
Recently as I needed to share DB classes among two websites I moved all DB classes to separate class library and referenced System.Web library which I know is bad practice, but it's working.
Now the next step is to include unit and module tests which as I read is very difficult or impossible when using HttpContext in library, so I want to get rid of System.Web references. What is the best practice for this situation?
I think I can't just pass HttpContext to GetEntityContext() as it is also called from within my entity classes. Although this probably can be refactored. So maybe this is where I should go?
I also wondered if is it possible to somehow pass current section ID to this whole library? It cannot be just static property because as far as I understand it would be common for all users using the application. This should be user-specific.
Reassuming the objective is to make automated testing possible without loosing transparent Connection String choosing and session timeouts handling.
If I do something fundamentally wrong at this stage please also let me know. I can look again at this question tomorrow morning (8.00 am UTC) so please don't be discouraged by my silence till then.
EDIT:
Example of usage of Connection class in the library:
public partial class Store
{
public static List<Store> GetSpecialStores()
{
using (var context = Connection.GetEntityContext())
{
return context.Stores.Where(qq => qq.Type > 0).OrderBy(qq => qq.Code).ToList();
}
}
}
You can declare interface IContextProvider inside your library ans use it to retrieve context. Something like:
public interface IContextProvider
{
MyEntities GetEntityContext();
}
This will make your library testable. In your web project you can inject IContextProvider implementation into your library.
public class WebContextProvider : IContextProvider
{
public MyEntities GetEntityContext()
{
if (HttpContext.Current.Session["section"] == null)
HttpContext.Current.Response.Redirect("~/Login.aspx");
int sectionId = (int)HttpContext.Current.Session["section"];
string connectionString = GetEntityConnectionStringForSection(sectionId);
var context = new MyEntities(connectionString);
return context;
}
private static string GetEntityConnectionStringForSection(int section)
{
switch (section)
{
case 1: return ConfigurationManager.ConnectionStrings["entity_1"].ConnectionString;
case 2: return ConfigurationManager.ConnectionStrings["entity_2"].ConnectionString;
case 3: return ConfigurationManager.ConnectionStrings["entity_3"].ConnectionString;
default: return ConfigurationManager.ConnectionStrings["entity_1"].ConnectionString;
}
}
}
Inject this interface to repositories or other data access classes.
public partial class Store
{
private IContextProvider contextProvider;
public Store(IContextProvider contextProvider)
{
this.contextProvider = contextProvider;
}
public List<Store> GetSpecialStores()
{
using (var context = contextProvider.GetEntityContext())
{
return context.Stores.Where(qq => qq.Type > 0).OrderBy(qq => qq.Code).ToList();
}
}
}