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/
Related
I been trying to figure out how i can unit test service and so far have got nowhere.
I am using xUnit and NSubstitute (as advised by friends), below is the simple test that i want to run (which fails currently).
public class UnitTest1
{
private readonly RallyService _rallyService;
public UnitTest1(RallyService rallyService)
{
_rallyService= rallyService;
}
[Fact]
public void Test1()
{
var result = _rallyService.GetAllRallies();
Assert.Equal(2, result.Count());
}
}
My rally service class makes a simple call to the db to get all Rally entites and returns those:
public class RallyService : IRallyService
{
private readonly RallyDbContext _context;
public RallyService(RallyDbContext context)
{
_context = context;
}
public IEnumerable<Rally> GetAllRallies()
{
return _context.Rallies;
}
}
Any guidance would be appreciated.
Since you use .NET Core, I assume you also use Entity Framework Core. While it was possible to mock most of the operations in the previous EF version, however the EF Core suggests to use in-memory database for unit testing. I.e. you don't need to mock RallyDbContext, hence NSubstitute is not needed for this particular test. You would need NSubstitute to mock the service when testing a controller or application using the service.
Below is your Test1 written using in-memory database.
public class UnitTest1
{
private readonly DbContextOptions<RallyDbContext> _options;
public UnitTest1()
{
// Use GUID for in-memory DB names to prevent any possible name conflicts
_options = new DbContextOptionsBuilder<RallyDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
}
[Fact]
public async Task Test1()
{
using (var context = new RallyDbContext(_options))
{
//Given 2 records in database
await context.AddRangeAsync(new Rally { Name = "rally1" }, new Rally { Name = "rally2" });
await context.SaveChangesAsync();
}
using (var context = new RallyDbContext(_options))
{
//When retrieve all rally records from the database
var service = new RallyService(context);
var rallies = service.GetAllRallies();
//Then records count should be 2
Assert.Equal(2, rallies.Count());
}
}
}
A working test application with this unit test is in my GitHub for your reference. I used SQL Express in the actual app.
I don't think it is standard to have a unit test constructor with a parameter. The unit test runner will new up this class, and unless you are using something that will auto-inject that parameter I think the test will fail to run.
Here is a standard fixture layout:
public class SampleFixture {
[Fact]
public void SampleShouldWork() {
// Arrange stuff we need for the test. This may involved configuring
// some dependencies, and also creating the subject we are testing.
var realOrSubstitutedDependency = new FakeDependency();
realOrSubstitutedDependency.WorkingItemCount = 42;
var subject = new Subject(realOrSubstitutedDependency);
// Act: perform the operation we are testing
var result = subject.DoWork();
// Assert: check the subject's operation worked as expected
Assert.Equal(42, result);
}
[Fact]
public void AnotherTest() { /* ... */ }
}
If you need a common setup between tests, you can use a parameterless constructor and do common initialisation there.
In terms of the specific class you are trying to test, you need to make sure your RallyDbContext is in a known state to repeatably and reliably test. You may want to look up answers specific to testing Entity Framework for more information.
I Would like to test my Hub in SignalR, what is the best approach?
Possible solutions I have thought about so far:
Create a testable Hub
Abstract logic to separate class
Selenium (would like to test smaller units)
Or is it some SignalR testing features have overlooked
Currently using SignalR 0.4, and NUnit as the testing framework.
This link shows how to unit test SignalR hub methods using Moq. You mock up the respository, clients, context, and the caller. Here's the code from the site, I made some minor changes to make it work with the latest SignalR:
public class TestableChatHub : ChatHub
{
public Mock<IChatRepository> MockChatRepository { get; private set; }
public TestableChatHub(Mock<IChatRepository> mockChatRepository)
: base(mockChatRepository.Object)
{
const string connectionId = "1234";
const string hubName = "Chat";
var mockConnection = new Mock<IConnection>();
var mockUser = new Mock<IPrincipal>();
var mockCookies = new Mock<IRequestCookieCollection>();
var mockRequest = new Mock<IRequest>();
mockRequest.Setup(r => r.User).Returns(mockUser.Object);
mockRequest.Setup(r => r.Cookies).Returns(mockCookies.Object);
Clients = new ClientProxy(mockConnection.Object, hubName);
Context = new HubCallerContext(mockRequest.Object, connectionId);
var trackingDictionary = new TrackingDictionary();
Caller = new StatefulSignalProxy(
mockConnection.Object, connectionId, hubName, trackingDictionary);
}
}
Then the site shows that you can use this testable hub to write unit tests:
[TestClass]
public class ChatHubTests
{
private TestableChatHub _hub;
public void SetUpTests()
{
_hub = GetTestableChatHub();
}
[Test]
public void ExampleTest()
{
SetUpTests();
const string message = "test";
const string connectionId = "1234";
var result = _hub.Send(message);
_hub.MockChatRepository.Verify(r => r.SaveMessage(message, connectionId));
Assert.IsTrue(result);
}
private TestableChatHub GetTestableChatHub()
{
var mockRepository = new Mock<IChatRepository>();
mockRepository.Setup(m => m.SaveMessage(
It.IsAny<string>(), It.IsAny<string())).Returns(true);
return new TestableChatHub(mockRepository);
}
}
It's quite simple to create to unit test SignalR hubs using a couple of neat tricks. One thing to note is that SignalR uses dynamic classes which might not be supported by your mocking framework (I use NSubstitute).
public class ProjectsHub: Hub
{
public void AddProject(string id)
{
Clients.All.AddProject(id);
}
}
[TestFixture]
public class ProjectsHubTests
{
// Operations that clients might receive
// This interface is in place in order to mock the
// dynamic object used in SignalR
public interface ISignals
{
void AddProject(string id);
}
[Test]
public void AddProject_Broadcasts()
{
// Arrange
ProjectsHub hub = new ProjectsHub();
IHubCallerConnectionContext clients =
Substitute.For<IHubCallerConnectionContext>();
ISignals signals = Substitute.For<ISignals>();
SubstituteExtensions.Returns(clients.All, signals);
hub.Clients = clients;
// Act
hub.AddProject("id");
// Assert
signals.Received(1).AddProject("id");
}
}
Rewriting this to use e.g. Moq should be pretty simple.
This question is from a while ago, but I'll do my best to answer anyway.
If you have a lot of logic in your actual hub class, it would certainly make sense to abstract the logic to a separate class. I did the same for my SignalR-powered multiplayer demo. The only behaviour that should go in your hub class itself is the one related to messaging. All further action should be delegated.
Note: This is very much like the guidelines for controller design in ASP .NET MVC: Keep your controllers small and delegate the real work.
If you want integration tests with SignalR actually doing some work, selenium webdriver would be a good option. But you will probably need to do some tweaking to get the SignalR messaging working perfectly in the context of the tests. Do a google search for "signalr selenium" (without the quotes) to get started on the right track.
Some blogposts about automated tests for SignalR => here and here
With the SignalR 2.0 you can do it this way:
// Arrange
var hub = new CodeInteractivePreviewHub();
var mockClients = new Mock<IHubCallerConnectionContext<dynamic>>();
hub.Clients = mockClients.Object;
dynamic all = new ExpandoObject();
mockClients.Setup(m => m.All).Returns((ExpandoObject)all);
// Act
var allSourceCodes = hub.InitiateCommunication(); //Change this line to your Hub's method
// Assert
Assert.IsNotNull(allSourceCodes);
This is modified version of Iarsm's answer, to work with XUnit and MOQ.
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using Moq;
using Xunit;
namespace TestLibrary {
public class ProjectsHub : Hub {
public void AddProject(string id) {
Clients.All.AddProject(id);
}
}
public class ProjectsHubTests {
// Operations that clients might receive
// This interface is in place in order to mock the
// dynamic object used in SignalR
public interface ISignals {
void AddProject(string id);
}
[Fact]
public void AddProject_Broadcasts() {
// Arrange
ProjectsHub hub = new ProjectsHub();
var clients = new Mock<IHubCallerConnectionContext<dynamic>>();
var signals = new Mock<ISignals>();
hub.Clients = clients.Object;
signals.Setup(m => m.AddProject(It.Is<string>(s => s == "id"))).Verifiable();
clients.Setup(m => m.All).Returns(signals.Object);
// Act
hub.AddProject("id");
// Assert
signals.VerifyAll();
}
}
}
My interface was out of the test project, but here's how I did it using NUnit and Moq.
using Microsoft.AspNetCore.SignalR;
using Moq;
using NUnit.Framework;
namespace TestLibrary
{
// Operations that clients might receive
// This interface is in place in order to mock the
// dynamic object used in SignalR
public interface ISignals
{
void AddProject(string id);
}
public class ProjectsHub : Hub<ISignals>
{
public void AddProject(string id)
{
Clients.All.AddProject(id);
}
}
public class ProjectsHubTests
{
[Test]
public void AddProject_Broadcasts()
{
// Arrange
ProjectsHub hub = new ProjectsHub();
var clients = new Mock<IHubCallerClients<ISignals>>();
var signals = new Mock<ISignals>();
hub.Clients = clients.Object;
signals.Setup(m => m.AddProject(It.Is<string>(s => s == "id"))).Verifiable();
clients.Setup(m => m.All).Returns(signals.Object);
// Act
hub.AddProject("id");
// Assert
signals.VerifyAll();
}
}
}
When unit testing with RavenDb, it is often the case that newly added data is retrieved or otherwise processed. This can lead to 'stale index' exceptions e.g.
Bulk operation cancelled because the index is stale and allowStale is false
According to a number of answers
How should stale indexes be handled during testing?
WaitForNonStaleResults per DocumentStore
RavenDb : Update a Denormalized Reference property value
The way to force the database (the IDocumentStore instance) to wait until its indexes are not stale before processing a query or batch operation is to use DefaultQueryingConsistency = ConsistencyOptions.QueryYourWrites during the IDocumentStore initialisation, like this:
public class InMemoryRavenSessionProvider : IRavenSessionProvider
{
private static IDocumentStore documentStore;
public static IDocumentStore DocumentStore
{
get { return (documentStore ?? (documentStore = CreateDocumentStore())); }
}
private static IDocumentStore CreateDocumentStore()
{
var store = new EmbeddableDocumentStore
{
RunInMemory = true,
Conventions = new DocumentConvention
{
DefaultQueryingConsistency = ConsistencyOptions.QueryYourWrites,
IdentityPartsSeparator = "-"
}
};
store.Initialize();
IndexCreation.CreateIndexes(typeof (RavenIndexes).Assembly, store);
return store;
}
public IDocumentSession GetSession()
{
return DocumentStore.OpenSession();
}
}
Unfortunately, the code above does not work. I am still receiving exceptions regarding stale indexes. These can be resolved by putting in dummy queries that include .Customize(x => x.WaitForNonStaleResultsAsOfLastWrite()).
This is fine, as long as these can be contained in the Unit Test, but what if they can't? I am finding that these WaitForNonStaleResults* calls are creeping into production code just so I can get unit-tests to pass.
So, is there a sure fire way, using the latest version of RavenDb, to force the indexes to freshen before allowing commands to be processed - for the purposes of unit testing only?
Edit 1
Here is a solution based on the answer give below that forces a wait until the index is not stale. I have written it as an extension method for the sake of unit-testing convenience;
public static class IDocumentSessionExt
{
public static void ClearStaleIndexes(this IDocumentSession db)
{
while (db.Advanced.DatabaseCommands.GetStatistics().StaleIndexes.Length != 0)
{
Thread.Sleep(10);
}
}
}
And here is a Unit Test that was using the verbose WaitForNonStaleResultsAsOfLastWrite technique but now uses the neater extension method.
[Fact]
public void Should_return_list_of_Relationships_for_given_mentor()
{
using (var db = Fake.Db())
{
var mentorId = Fake.Mentor(db).Id;
Fake.Relationship(db, mentorId, Fake.Mentee(db).Id);
Fake.Relationship(db, mentorId, Fake.Mentee(db).Id);
Fake.Relationship(db, Fake.Mentor(db).Id, Fake.Mentee(db).Id);
//db.Query<Relationship>()
// .Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
// .Count()
// .ShouldBe(3);
db.ClearStaleIndexes();
db.Query<Relationship>().Count().ShouldBe(3);
MentorService.GetRelationships(db, mentorId).Count.ShouldBe(2);
}
}
If you have a Map/Reduce index, DefaultQueryingConsistency = ConsistencyOptions.QueryYourWrites won't work. You need to use an alternative method.
In your units tests, call code like this, straight after you've inserted any data, this will force the all indexes to update before you do anything else:
while (documentStore.DatabaseCommands.GetStatistics().StaleIndexes.Length != 0)
{
Thread.Sleep(10);
}
Update You can of course put it in an extension method if you want to:
public static class IDocumentSessionExt
{
public static void ClearStaleIndexes(this IDocumentSession db)
{
while (db.Advanced.DatabaseCommands.GetStatistics().StaleIndexes.Length != 0)
{
Thread.Sleep(10);
}
}
}
Then you can say:
db.ClearStaleIndexes();
You can actually add a query listener on the DocumentStore to wait for nonstale results. This can be used just for unit tests as it is on the document store and not each operation.
// Initialise the Store.
var documentStore = new EmbeddableDocumentStore
{
RunInMemory = true
};
documentStore.Initialize();
// Force queries to wait for indexes to catch up. Unit Testing only :P
documentStore.RegisterListener(new NoStaleQueriesListener());
....
#region Nested type: NoStaleQueriesListener
public class NoStaleQueriesListener : IDocumentQueryListener
{
#region Implementation of IDocumentQueryListener
public void BeforeQueryExecuted(IDocumentQueryCustomization queryCustomization)
{
queryCustomization.WaitForNonStaleResults();
}
#endregion
}
#endregion
(Shamelessly stolen from RavenDB how to flush?)
Be aware that StaleIndexes also include abondoned and disabled indices - which will never get up to date.
So to avoid waiting indefinetely use this property instead:
var staleIndices = store.DatabaseCommands.GetStatistics().CountOfStaleIndexesExcludingDisabledAndAbandoned;
I am unit testing my controller.
In one of my controller methods I am setting Session variables:
public void Index(){
Session["foo"] = "bar";
return View();
}
How can I unit test this? The problem is that the Session property is null when testing. Injecting is not possible because the Session property is readonly.
[TestMethod]
public void TestIndex()
// When
_controller.Index();
// Then
Assert.AreEqual("bar", _controller.Session["foo"])
Personally I like using the MvcContrib TestHelper which mocks all the HTTP pipeline:
[TestMethod]
public void HomeController_Index_Action_Should_Store_Bar_In_Session()
{
// arrange
var sut = new HomeController();
new TestControllerBuilder().InitializeController(sut);
// act
sut.Index();
// assert
Assert.AreEqual("bar", (string)sut.Session["foo"]);
}
This is what I used for Unit Test friendly Session Caching. By checking HttpContext.Current for null, you're by passing the caching for nunit tests and still allow your program to function normally.
This is the simplest solution without making a lot of code changes in your project.
internal class SessionCache
{
public static void Store(string key, object val) {
if (HttpContext.Current != null) {
HttpContext.Current.Session[key] = val;
}
}
public static object Retrieve(string key) {
if (HttpContext.Current != null) {
return HttpContext.Current.Session[key];
}
return null;
}
}
I always recommend wrapping the session object in another object. This not only gives you an easier way to test, but also makes all access to the session type safe. It is very easy to mistype a session key name in one spot in one place and then hunt for the bug for hours.
The object would have fields as
public Foo{
get{return Session["Foo"];}
set{Session["Foo"]=value;}
}
Once you are testing you can mock the session class with a dummy that only keeps state for the test.
The way I usually handle this is with dependency injection. How to set this up is a long examination. Here is a link to one way
http://weblogs.asp.net/shijuvarghese/archive/2011/01/21/dependency-injection-in-asp-net-mvc-3-using-dependencyresolver-and-controlleractivator.aspx
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.