I am taking my first steps with MsTest and Moq and would like to unit test a Linq2SQL repository class. The problem is that I do not want the unit tests to permantly modify my development database.
Which would be the best approach for this scenario?
Let each test operate on my real development database, but make sure each test cleans up after itself
Create a duplicate of my development database and dbml for the unit test and use that context instead so I can clear the entire database before each test run
Find some elaborate way of mocking the Datacontext (please bear in mind that I am a total Moq noob).
Something completely different? Perhaps something that would automate setting up the database for me before each test run?
Edit: I just learned that MBUnit has a rollback attribute that reverses any database operations run by a test case. I am not particularly attached to MSTest, so could this be an easy answer to my problem?
I went with mocking/faking the database using some wrapper classes + a fake implementation based on http://andrewtokeley.net/archive/2008/07/06/mocking-linq-to-sql-datacontext.aspx. Note that I did end up implementing SubmitChanges logic in my fake data context wrapper to test out the validation logic in my entity's partial class implementation. I think that this was really the only tricky part which differed substantially from Tokeley's implementation.
I'll include my FakeDataContextWrapper implementation below:
public class FakeDataContextWrapper : IDataContextWrapper
{
public DataContext Context
{
get { return null; }
}
private List<object> Added = new List<object>();
private List<object> Deleted = new List<object>();
private readonly IFakeDatabase mockDatabase;
public FakeDataContextWrapper( IFakeDatabase database )
{
mockDatabase = database;
}
protected List<T> InternalTable<T>() where T : class
{
return (List<T>)mockDatabase.Tables[typeof( T )];
}
#region IDataContextWrapper Members
public virtual IQueryable<T> Table<T>() where T : class
{
return mockDatabase.GetTable<T>();
}
public virtual ITable Table( Type type )
{
return new FakeTable( mockDatabase.Tables[type], type );
}
public virtual void DeleteAllOnSubmit<T>( IEnumerable<T> entities ) where T : class
{
foreach (var entity in entities)
{
DeleteOnSubmit( entity );
}
}
public virtual void DeleteOnSubmit<T>( T entity ) where T : class
{
this.Deleted.Add( entity );
}
public virtual void InsertAllOnSubmit<T>( IEnumerable<T> entities ) where T : class
{
foreach (var entity in entities)
{
InsertOnSubmit( entity );
}
}
public virtual void InsertOnSubmit<T>( T entity ) where T : class
{
this.Added.Add( entity );
}
public virtual void SubmitChanges()
{
this.SubmitChanges( ConflictMode.FailOnFirstConflict );
}
public virtual void SubmitChanges( ConflictMode failureMode )
{
try
{
foreach (object obj in this.Added)
{
MethodInfo validator = obj.GetType().GetMethod( "OnValidate", BindingFlags.Instance | BindingFlags.NonPublic );
if (validator != null)
{
validator.Invoke( obj, new object[] { ChangeAction.Insert } );
}
this.mockDatabase.Tables[obj.GetType()].Add( obj );
}
this.Added.Clear();
foreach (object obj in this.Deleted)
{
MethodInfo validator = obj.GetType().GetMethod( "OnValidate", BindingFlags.Instance | BindingFlags.NonPublic );
if (validator != null)
{
validator.Invoke( obj, new object[] { ChangeAction.Delete } );
}
this.mockDatabase.Tables[obj.GetType()].Remove( obj );
}
this.Deleted.Clear();
foreach (KeyValuePair<Type, IList> tablePair in this.mockDatabase.Tables)
{
MethodInfo validator = tablePair.Key.GetMethod( "OnValidate", BindingFlags.Instance | BindingFlags.NonPublic );
if (validator != null)
{
foreach (object obj in tablePair.Value)
{
validator.Invoke( obj, new object[] { ChangeAction.Update } );
}
}
}
}
catch (TargetInvocationException e)
{
throw e.InnerException;
}
}
public void Dispose() { }
#endregion
}
I had a similar need - to unit test the Linq to Sql classes, so I made a small set of classes to get mock datacontext, ITables and IQueryables into the queries.
I put the code in a blog post "Mock and Stub for Linq to Sql". It uses Moq, and might provide enough functionality for the tests you're after without hitting the database.
I played a bit with MBUnit and learned that, for most test cases, you can get away without mocking the datacontext by using MBUnit's [ROLLBACK] attribute.
Unfortunately there are also cases when the attribute produces strange side effects, such as loading a linq entity from the database, changing one property (without submitchanges), then loading the same entity again. Usually this results in no update query on the database, but from within the Test Method it appears as if the update is immediately executed as soon as I change the linq entity property.
Not a perfect solution, but I think I'll go with the [ROLLBACK] attribute since it's less effort and works well enough for me.
Related
I'm writing this because I've tried for a bit to figure this out myself with no luck. Every example I can find for whatever reason seems to suggest that this just works out of the box but whenever I try to do the same, I always get errors. Basically, I have a controller with two properties that are injected via. DI, let's say
public class SomeController
{
private ISomeInterface _i;
private MyConfig _c;
public SomeController(ISomeInterface i, MyConfigContext cxt) // Where cxt is Type of DbContext
{
_i = i;
_c = cxt.Configs.FirstOrDefault();
}
public OkResult PostModel(SomeModel c)
{
// Do things
return Ok();
}
}
And in my tests using xUnit, Moq & AutoFixture I'm trying to avoid having to manually instantiate dependencies B and C:
public class SomeControllerTests
{
private MyDbContext _cxt;
private Fixture _fixture;
public SomeControllerTests()
{
_cxt = GetCxt() // GetCxt() just returns a context instance, nothing special
_fixture = new Fixture();
_fixture.Customize(new AutoMoqCustomization { ConfigureMembers = true });
_fixture.Customizations.Add(
new TypeRelay(
typeof(ISomeInterface),
typeof(SomeConcreteClass)
)
);
}
[Fact, AutoData]
public void PostStatus_ReturnsOk_GivenValidRequest()
{
SomeController c = _fixture.Create<SomeController>();
SomeModel m = _fixture.Create<SomeModel>();
var result = c.PostModel(m);
Asset.IsType<OkResult>(result);
}
}
With the above I am getting a NotImplementedException when I run the tests and it won't tell me what exactly is not being implemented so I have no way of knowing what the issue is. I must be missing something in the docs. I want to use AutoFixture to make my tests more durable but so far it has been a pain trying to use it. I really don't want to have to mock/stub my entire app manually just to run a test. I would ideally like to use the syntax shown in the AutoFixture docs where you put your test-relevant instances in the params of the test and they are created for you but I haven't had any luck with it, like...
[Theory, AutoData]
SomeTestMethod(SomeController c, SomeModel m)
{
var result = c.PostModel(m);
Assert.IsType<OkResult>(result);
}
Thanks for Reading (:
Try to add next attribute and use it instead of AutoData.
using AutoFixture.AutoMoq;
using AutoFixture.Xunit2;
namespace Cats
{
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute()
: base(() => new Fixture().Customize(new AutoMoqCustomization()))
{
}
}
}
[Theory, AutoMoqData]
SomeTestMethod(SomeController c, SomeModel m)
{
var result = c.PostModel(m);
Assert.IsType<OkResult>(result);
}
I would like to write a non-regression test to validate that transient components are well released. Some are created by a direct injection in ctor, other by typed factories.
I thought that I could do this way:
// Given
var rootComponent = container.Resolve<IRootComponent>();
var c1 = rootComponent.C1;
var c2 = c1.C2;
etc.
Assert.True(Container.Kernel.ReleasePolicy.HasTrack(c1));
Assert.True(Container.Kernel.ReleasePolicy.HasTrack(c2));
// When
c1.Close();
// Then
Assert.False(Container.Kernel.ReleasePolicy.HasTrack(c1));
Assert.False(Container.Kernel.ReleasePolicy.HasTrack(c2));
HasTrack() always returns false, although if I look at the container in debug mode, I can see my components well tracked. Why is that? Do you have any suggestion for such a test?
Thx for your help
The reason that your components are not tracked is that the component and it's dependencies have no decomissioning requirements. In this case there is no reason for windsor to track them.
When using windsor in general you should only resolve on your container once to obtain your top level component. All other component are either injected or created by a factory. There is no need to worry about the live time of injected components. The container will handle it for you.
For transient components that you create with a factory you should be aware that they will never live (be tracked) longer then the factory it self. So if you don't mind that your components live at long as your factory there is no need to release them (using a destroy method on a factory).
For component that I want to make sure that I release them, I generally I create unit test for which I stub out the factory. That way it is easy to test that destroy is called.
I think with the approach that you are taking you are not just testing your code but also the container. IMHO windsor is already well tested, and test should focus on your own code.
Good luck,
Marwijn.
Two years too late, but here's a test.
public class DependsOnSomethingDisposable
{
private readonly SomethingDisposable _disposable;
public Boolean SomethingDisposableIsDisposed { get { return _disposable.Disposed; } }
public DependsOnSomethingDisposable(SomethingDisposable disposable)
{
_disposable = disposable;
}
}
public class SomethingDisposable : IDisposable
{
public Boolean Disposed { get; private set; }
public void Dispose()
{
Disposed = true;
}
}
[TestClass]
public class WindsorLifestyleTests
{
private IWindsorContainer _container;
[TestInitialize]
public void Setup()
{
_container = new WindsorContainer();
}
[TestCleanup]
public void Cleanup()
{
_container.Dispose();
}
[TestMethod]
public void TransientDependencyIsDisposed()
{
_container.Register(
Component.For<DependsOnSomethingDisposable>().LifestyleTransient(),
Component.For<SomethingDisposable>().LifestyleTransient()
);
var resolved = _container.Resolve<DependsOnSomethingDisposable>();
_container.Release(resolved);
Assert.IsTrue(resolved.SomethingDisposableIsDisposed);
}
[TestMethod]
public void NonTransientDependencyIsNotDisposed()
{
_container.Register(
Component.For<DependsOnSomethingDisposable>().LifestyleTransient(),
Component.For<SomethingDisposable>().LifestyleSingleton()
);
var resolved = _container.Resolve<DependsOnSomethingDisposable>();
_container.Release(resolved);
Assert.IsFalse(resolved.SomethingDisposableIsDisposed);
}
}
I wrote the following customization and have it applied as part of a composite on most of my tests. My entities have a read-only Id, but I'm using their SetId method in this customization to make sure all entities have some Id if they are transient (don't have an Id already).
public class SetEntityIdCustomization : ICustomization {
public void Customize(IFixture fixture) {
var engine = ((Fixture)fixture).Engine;
fixture.Customizations.Add(new Postprocessor(
engine, o => {
var entity = o as BaseEntity;
if (entity == null || !entity.IsTransient()) {
return;
}
entity.SetId(fixture.CreateAnonymous<Guid>());
}));
}
}
This has been working great, until I discovered a very odd thing today. If I feed a test one of my entities that directly inherits from BaseEntity, all is well and it's writeable properties are auto-filled. However, if I ask for an entity that inherits from something further down from BaseEntity, my customization prevents the properties from auto-filling.
The User entity in this test method is filled properly:
public class User : BaseEntity {
public string Email { get; set; }
public int CoolThings { get; set; }
}
...
[Theory, AutoDomainData]
public void SomeTest(User user, ...) {
// user.Email and user.CoolThings have auto-filled values, as expected.
...
}
However, the AwesomeUser entity in the following test does not get any of the same properties auto-filled.
public class AwesomeUser : User {
...
}
...
[Theory, AutoDomainData]
public void SomeOtherTest(AwesomeUser user, ...) {
// user.Email nor user.CoolThings have auto-filled values. What gives?
...
}
In both test cases, the Id property is auto-filled because of my customization. If I remove my customization, the SomeOtherTest's AwesomeUser instance gets its inherited properties auto-filled just fine. I must assume that my customization is what is messing things up.
Is there a better way to get all my BaseEntity instances to set their Id, or is there something else I'm missing with AutoFixture? I've applied my customization first, in the middle, and last, to no avail.
The solution provided above is a pretty clever attempt, but not something I've seen before. A more idiomatic solution would be something like this:
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(
new FilteringSpecimenBuilder(
new Postprocessor(
new BaseEntityBuilder(
new ConstructorInvoker(
new ModestConstructorQuery())),
new AutoPropertiesCommand().Execute),
new BaseEntitySpecification()));
}
private class BaseEntityBuilder : ISpecimenBuilder
{
private readonly ISpecimenBuilder builder;
private readonly IRequestSpecification specification;
public BaseEntityBuilder(ISpecimenBuilder builder)
{
this.builder = builder;
this.specification = new BaseEntitySpecification();
}
public object Create(object request, ISpecimenContext context)
{
if (!this.specification.IsSatisfiedBy(request))
return new NoSpecimen(request);
var b = (BaseEntity)this.builder.Create(request, context);
b.SetId((Guid)context.Resolve(typeof(Guid)));
return b;
}
}
private class BaseEntitySpecification : IRequestSpecification
{
public bool IsSatisfiedBy(object request)
{
var t = request as Type;
if (t == null)
return false;
if (!typeof(BaseEntity).IsAssignableFrom(t))
return false;
return true;
}
}
As you can see, this isn't a simple one-liner, which is indicative of AutoFixture being a rather opinionated library. In this case, AutoFixture's opinion is:
Favor object composition over class inheritance.
-Design Patterns, p. 20
AutoFixture is first and foremost a TDD tool, and one of the main advantages of TDD is that it provides feedback about class design. In this case, the feedback is: Inheritance is awkward and troublesome. Reconsider the design.
I've got the following code and I need help to write a unit test for it. I'm using Moq library.
Here's the deal. I have a business class with a dependency to a repository (interface), so I can use it to save my entities to the database. My entity is basically a list of strings. The method AddAndSave, from MyBusinessClass, grab the value it receives as a parameters, put it into the list and call Save method from IRepository. Then, I clear the list of my entity. The code below show this example (I've made it simple so I can explain it here).
There's a unit test, too.
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace TestesGerais
{
public class MyEntity
{
public MyEntity()
{
MyList = new List<string>();
}
public List<string> MyList { get; set; }
}
public interface IRepository
{
void Save(MyEntity entity);
}
public class MyBusinessClass
{
public IRepository Repository { get; set; }
private MyEntity _entity = new MyEntity();
public void AddAndSave(string info)
{
_entity.MyList.Add(info);
Repository.Save(_entity);
_entity.MyList.Clear(); // for some reason I need to clear it
}
}
[TestClass]
public class UnitTest10
{
[TestMethod]
public void TestMethod1()
{
var mock = new Mock<IRepository>();
MyBusinessClass b = new MyBusinessClass() { Repository = mock.Object };
b.AddAndSave("xpto");
mock.Verify(m => m.Save(It.Is<MyEntity>(x => x.MyList[0] == "xpto")), Times.Exactly(1));
}
}
}
My unit-test check if the IRepository's Save method was called with its parameter (an entity) having one element in the list, and having the value "xpto" in this element.
When I run this test, it turns red with the error message "Test method TestesGerais.UnitTest10.TestMethod1 threw exception:
System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index".
Ok, this is caused by the list that has been cleaned. If I comment the line "_entity.MyList.Clear();", everything goes well.
My question is: how can I test this without commenting the "Clear" line in my business class, and making sure that my repository's method is called passing the specific value (entity with one element with value "xpto")?
Thanks
I've changed my unit test using the Callback feature of Moq. This way, I can setup the mock so when AddAndSave is called, the parameter it receives is saved into a variable from my unit test, and I can assert it later.
[TestMethod]
public void TestMethod1()
{
var mock = new Mock<IRepository>();
string result = string.Empty;
mock.Setup(m => m.Save(It.IsAny<MyEntity>())).Callback((MyEntity e) => { result = e.MyList[0]; });
MyBusinessClass b = new MyBusinessClass() { Repository = mock.Object };
b.AddAndSave("xpto");
Assert.AreEqual(result, "xpto");
}
You could split your method up a bit. "AddAndSave" isn't all it does. You could then just test the behaviour of the adding and saving bit in isolation.
i'm building some basic crud methods for my fluently mapped entities.
i just wanna know if there is a simple way to make the transaction to perform a rollback when i'm running the cud test methods ?
the code that being tested perform the commit inside
here is a create sample:
public int? Create(IIdentifiable entity)
{
int? newId = null;
using (ISession session = SessionFactoryProvider.NewSession)
using (ITransaction transaction = session.BeginTransaction())
{
object newObj = session.Save(entity);
newId = (int?)newObj;
transaction.Commit();
}
return (int?)newId;
}
If you're using xUnit.net, there's an AutoRollback attribute in the contrib project. If you're open to using System.Transactions then you can create a new transaction before the session.Open() and session should autoenlist (unless you've set ado.net to not autoenlist). Then just abandon at the end.
I did something similar to this a (long) while ago:
public class TransactionalTest
{
public TransactionalTest()
{
Transaction.Current = new CommittableTransaction();
}
~TransactionalTest()
{
if (Transaction.Current != null &&
Transaction.Current.TransactionInformation.Status !=
TransactionStatus.Committed)
{
Transaction.Current.Rollback();
}
}
}
Then just have your test extend TransactionalTest. But, I think NUnit, MbUnit and xUnit.net all support transactional tests out of the box or with a contrib project.
Check FUBUMVC Contrib for a great NHibernate CRUD testing method.
Hmm, I don't think that it is a good idea to let your method create a session and perform transaction handling .... Unless that method is also a service boundary.
Suppose you want to create multiple entities in one and the same transaction, how are you going to handle that ?
For integration testing, I use a session decorator to auto commit and evict the entity. You could adapt it for your situation:
public class AutoCommitAndEvictSession : SessionDecorator {
public AutoCommitAndEvictSession(ISession session)
: base(session) { }
public override object Save(object obj) {
object result;
using (var tx = Session.BeginTransaction()) {
result = Session.Save(obj);
tx.Commit();
}
Session.Evict(obj);
return result;
}
public override void Update(object obj) {
CommitAndEvict(base.Update, obj);
}
public override void Delete(object obj) {
CommitAndEvict(base.Delete, obj);
}
private void CommitAndEvict(Action<object> action, object entity) {
using (var tx = Session.BeginTransaction()) {
action.Invoke(entity);
tx.Commit();
}
Session.Evict(entity);
}
}
You can find more details on usage with examples here:
http://www.agileatwork.com/integration-testing-with-nhibernate/