NullRefernceException when calling Setup - nunit

I'm trying to do a simple Setup on mocked object, but I always get a NullRefernceException coming from the setup line:
What is the mistake that I am doing here?

Your setup is incorrect because you are confusing Moq with the .ToString() in the It.IsAny<string>().ToString().
Because of this Moq cannot generate the correct matcher and throws an exception.
It is very easy to fix this, just remove the .ToString():
[Test]
public void Test()
{
mockDatabase = new Mock<IDatabase>();
DataSet ds = new DataSet();
mockDatabase.Setup(m => m.DbQuery(It.IsAny<string>())).Returns(ds);
var sut = new BusinessClass(mockDatabase.Object);
sut.SomeMethod();
}

Related

Register more than one mock or service using AutoMock.GetLoose() (Autofac.Extras.Moq)

I'm in the process of upgrading our Autofac.Extras.Moq library to the latest version (6.0.0) within our Unit Test project. After upgrading, I noticed tests using: var mock = AutoMock.GetLoose(), no longer supported the "Provide" method. So I started digging into the documentation for some sort of workaround.
After taking a look at the Getting Started docs (https://autofaccn.readthedocs.io/en/v5.2.0/integration/moq.html#getting-started) I've noticed there is a new way of registering mocks and dependent services using AutoMock.GetLoose(cfg => cfg.RegisterMock(mockA)). However, some of our tests require more than one Mock injected, and it's not clear to me how to do this.
Take for example:
[Test]
public void Test()
{
var mockA = new Mock();
mockA.Setup(x => x.RunA());
var mockB = new Mock();
mockB.Setup(x => x.RunB());
// mockA is automatically registered as providing IServiceA
using (var mock = AutoMock.GetLoose(cfg => cfg.RegisterMock(mockA)))
{
// mockA will be injected into TestComponent as IServiceA
var component = mock.Create();
// ...and the rest of the test
}
}
How would I register both mockA and mockB?
Thanks.
Have you tried putting both registrations in the GetLoose lambda?
[Test]
public void Test()
{
var mockA = new Mock();
mockA.Setup(x => x.RunA());
var mockB = new Mock();
mockB.Setup(x => x.RunB());
// Register both mocks here:
using (var mock = AutoMock.GetLoose(cfg => {
cfg.RegisterMock(mockA);
cfg.RegisterMock(mockB);
}))
{
// ...and the rest of the test
}
}
If you tried this and it didn't work, you should update your question to include both:
That you tried it AND
What the exception message or incorrect result was
Otherwise, if this works... 🎉

MiniProfiler setup - A null was returned after calling the 'get_ProviderFactory' method

After hours of struggling with MiniProfiler to make it profile the Database queries, I have no luck and I'm getting the error:
A null was returned after calling the 'get_ProviderFactory' method on
a store provider instance of type
'StackExchange.Profiling.Data.ProfiledDbConnection'. The store
provider might not be functioning correctly.
I got through many SO posts but nothing has worked so far, like this post which is about the same error but with different configuration and well there's not an answer. Now I know that ProfiledDbConnection is not overriding DbProviderFactory and it's parent class DbConnection returns null in it's implementation of DbProviderFactory so the error is expectable but it should work somehow. There is a MiniProfilerEF.Initialize() but it seams to be usable for CodeFirst only and I'm using DatabaseFirst approach.
I have installed MiniProfiler, MiniProfiler.EF, MiniProfilerMVC3 nuget packages. And here is my code:
string connectionString = ConfigurationManager.ConnectionStrings["SqlConnection"].ConnectionString;
var sqlConnection = new SqlConnection(connectionString);
var profiled = new ProfiledDbConnection(sqlConnection, MiniProfiler.Current);
var db = new DbContext(profiled, true);
db.Set<Customer>().ToList();
And I'm using asp.net mvc4, EF5, DatabseFirst, MiniProfiler 2.1.0.0, Sql Server
Any Idea?
So, coming from your comment on Setup of mvc-mini-profiler for EF-db- first, have you tried removing the Mini Profiler-specific wrapper?
var profiled = new ProfiledDbConnection(sqlConnection, MiniProfiler.Current);
var db = new DbContext(profiled, true);
db.Set<Customer>().ToList();
Instead, just adding
protected void Application_Start()
{
// any other code
MiniProfilerEF.Initialize();
}
and then doing standard db access?
using (var db = new WordsEntities()) {
var posts = db.Customer.Take(4);
// more code
}

MSTest fails when I do run all, but works otherwise

So I have a Testclass using MSTest and every test works great if I run them one and one, however if I select 2 tests, namely can_register and cannot_Register_existing_username then the second fails (cannot_register_existing_username).
I have let my testclass inherit from an abstract class that looks like this:
public abstract class RollbackCapabilities
{
private TransactionScope _transactionScope;
[TestInitialize]
public virtual void TestInitialize()
{
_transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions { Timeout = new TimeSpan(0, 10, 0) });
}
[TestCleanup]
public virtual void TestCleanup()
{
Transaction.Current.Rollback();
_transactionScope.Dispose();
}
}
If I comment this file out then it works (but now the data remains in the test-db which I don't want).
With this file above active the second test fails, the tests look like this
[TestMethod]
public void Can_Register()
{
//Arrange
AccountController ac = ControllerFactory.CreateAccountController();
RegisterModel model = new RegisterModel();
model.UserName = "TestUser";
model.Password= "TestPassword";
model.ConfirmPassword = "TestPassword";
//Act
ActionResult result = ac.Register(model);
//Assert
Assert.IsInstanceOfType(result, typeof(RedirectToRouteResult));
Assert.AreEqual("Home", ((RedirectToRouteResult)result).RouteValues["controller"]);
Assert.AreEqual("Index", ((RedirectToRouteResult)result).RouteValues["action"]);
}
[TestMethod]
public void Cannot_Register_Existing_Username()
{
//Arrange
AccountController ac = ControllerFactory.CreateAccountController();
RegisterModel model = new RegisterModel();
model.UserName = "TestUser";
model.Password = "TestPassword";
model.ConfirmPassword = "TestPassword";
ac.Register(model);
RegisterModel model2 = new RegisterModel();
model2.UserName = "TestUser";
model2.Password = "OtherTestPassword";
model2.ConfirmPassword = "OtherTestPassword";
//Act
ActionResult result = ac.Register(model2);
//Assert
Assert.IsInstanceOfType(result, typeof(ViewResult));
Assert.AreEqual("", ((ViewResult)result).ViewName);
Assert.AreEqual(model2, ((ViewResult)result).ViewData.Model);
}
and finally the error i get is as follows:
Test method
Viducate.UnitTests.UserHandling.RegisterTests.Cannot_Register_Existing_Username
threw exception: System.Data.EntityCommandExecutionException: An
error occurred while executing the command definition. See the inner
exception for details. ---> System.Data.SqlClient.SqlException:
Invalid object name 'dbo.Users'.
Thats my problem, not big but very annoying and as mentioned if I run the tests one and one it works, it also works but leaves data in the db if I comment out my RollbackCapabilities class
Okay so I found out that my error was that I had created the database (but not tables) by hand because create database is not supported in multi-transaction.
however creating an empty database means that EF assumes there is tables already and that is why it failed with dont know what dbo.users are.
So what I did was created the tables as well and now it works. However this means I can never run this on a new development machine without first creating the tables and database. so annoying.
I think I will set up another test class that does not inherit my abstract rollback class and hade that create the tables permanently... should solve the problem as long as that runs first.

UrlHelper's RouteUrl returning Empty String in Tests

I am having an issue where UrlHelper's RouteUrl method only returns an empty string when run in my tests, though function properly when executing in the real HttpContext. It is, however, finding the route - as I do properly get an exception if I try to resolve a route name which has not been defined.
I have mocked the HttpContext and friends using the code provided by Scott Hanselman/Kzu and added the code needed to bootstrap the Application's Routes into the mocked instance
To reduce the number of variables in my situation, I've written a simple test:
[Test]
public void UrlHelperReturnsCorrectUrl()
{
var controller = new MyController();
controller.SetFakeControllerContext().LoadUrlHelper();
Assert.AreEqual("My/Route/Path", controller.Url.RouteUrl("MyRoute"));
}
Interestingly enough, accessing the RouteCollection directly and using VirtualPath does work:
[Test]
public void GetVirtualPathReturnsCorrectUrl()
{
var controller = new AccountController();
controller.SetFakeControllerContext().LoadUrlHelper();
Assert.AreEqual("My/Route/Path",
Controller.Url.RouteCollection["MyRoute"]
.GetVirtualPath(
controller.Url.RequestContext,
new RouteValueDictionary())
.VirtualPath);
}
For reference, Here is my implementation of the LoadUrlHelper extension method:
public static Controller LoadUrlHelper(this Controller controller)
{
var routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);
controller.Url = new UrlHelper(
controller.ControllerContext.RequestContext,
routes);
return controller;
}
And here is my route as defined in my application's Global.asax:
routes.MapRoute(
"MyRoute", "My/Route/Path",
new {controller = "Home", action = "Index"});
Has anyone run into this? Am I missing something?
EDIT:
I've followed the MVC code down to the point that it hands the route processing off to System.Routing and found something very interesting. The code that MVC eventually runs to lookup the desired URL (condensed, of course) returns an empty string:
Controller.Url.RouteCollection.GetVirtualPath(
Controller.Url.RequestContext,
"MyRoute", new RouteValueDictionary()).VirtualPath;
whereas an extremely similar variant returns the expected string:
Controller.Url.RouteCollection["MyRoute"].GetVirtualPath(
Controller.Url.RequestContext,
new RouteValueDictionary()).VirtualPath;
I can't seem to go any further in the underlying code to see what is actually happening differently here, but thought it might help someone understand what setup I am missing. (I'm not going to yell bug yet, as the fact stands that the UrlHelpers do work when in a real HttpContext)
The solution to my problem was already posted to another SO question.
I had tried to incorporate this solution piece-meal earlier but did so poorly. Once I copied it entirely and modified for my situation, it worked perfectly.
Here is a more generic version that can be reused across many tests (if placed in a base test fixture class or something similar).
Usage:
var controller = GetController<MyController>();
controller.MyAction();
//...
Method:
protected T GetController<T>() where T : Controller, new()
{
var routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);
var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
request.SetupGet(x => x.ApplicationPath).Returns("/");
request.SetupGet(x => x.Url).Returns(new Uri("http://localhost", UriKind.Absolute));
request.SetupGet(x => x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection());
var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
response.Setup(x => x.ApplyAppPathModifier(It.IsAny<string>())).Returns((string p) => p);
var context = new Mock<HttpContextBase>(MockBehavior.Strict);
context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);
var controller = new T();
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
controller.Url = new UrlHelper(new RequestContext(context.Object, new RouteData()), routes);
return controller;
}

ControllerContext.IsChildAction invocation failed with mock behavior Strict. All invocations must have a setup

I am toying around to learn how to unit test ASP.NET MVC controller actions. Specifically I'm trying to mock the ControllerContext so that I can test an action that accesses HttpContext.Current.User.Identity.Name.
I'm using Moq.
Things were going pretty well until I turned on MockBehavior.Strict. I knew that this would throw an exception if the code failed to call the thing that I marked Verifiable. Apparently, it will also throw an exception if "extra" methods where I don't provide a setup (like IsChildAction) don't get called.
[TestMethod]
public void Index_Get_AccessesUserIdentityName()
{
// Arrange
var mock = new Mock<ControllerContext>(MockBehavior.Strict);
mock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns("treycarroll").Verifiable();
HomeController controller = new HomeController();
controller.ControllerContext = mock.Object;
// Act
ViewResult result = controller.Index() as ViewResult;
// Assert
mock.Verify();
...
}
Here is the Controller action that I'm testing:
public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!"+User.Identity.Name;
return View();
}
The exception is triggered when the return View(); statement is executed. The error message tells me that I need a setup method for the call to IsChildAction so I updated my test class to this:
[TestMethod]
public void Index_Get_AccessesUserIdentityName()
{
// Arrange
var mock = new Mock<ControllerContext>(MockBehavior.Strict);
string expectedUserName = "treycarroll";
mock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(expectedUserName).Verifiable();
mock.SetupGet(m => m.IsChildAction).Returns(true).Verifiable();
HomeController controller = new HomeController();
controller.ControllerContext = mock.Object;
// Act
ViewResult result = controller.Index() as ViewResult;
string actualUserName = controller.ControllerContext.HttpContext.User.Identity.Name;
// Assert
mock.Verify();
Assert.AreEqual(actualUserName, expectedUserName);
Assert.IsNotNull(result);
}
...
After which I get a similar error about no setup method for ControllerContext.RouteData. By process of elimination I could wind up adding Setup methods for all the missing calls, but this doesn't seem right. Maybe I'm misunderstanding the use of MockBehavior.Strict, but I thought that you turn this on in order to avoid getting default values for your properties (such as null for the User object that I want to inspect). What am I missing here?
A strict mock will fail immediately if anything differs from the expectations. So this means, that if any method call not specified in expectation will fail. On the other hand, a non-strict mock ignore, such calls