This is my first unit test and wanted some help clearing out my thoughts about the process of writing a unit test.
I wanted to write a test method that will add a new user - using my AddUser method in my library class.
Document doc = new Document();
[TestMethod]
public string AddUser()
{
string name = doc.AddUser("Testing User");
Assert.IsNotNull(name);
}
The error I am getting on build:
Cannot implicitly convert type void to string
This is my AddUser method:
public void AddUser(string newUserName)
{
using (var db = new DataContext())
{
User user = new User()
{
FullName = newUserName,
ID = Guid.NewGuid()
};
db.Users.InsertOnSubmit(user);
db.SubmitChanges();
}
}
Your method does not have a return value:
public void AddUser
^^^^ no return value
So you can't store it into a string:
string name = doc.AddUser("Testing User");
^^^^^^^^^^^ AddUser has no return value
Make sure you return the name from from your AddUser(string newUserName) method.
Replace your method like
public String AddUser(string newUserName)
{
using (var db = new DataContext())
{
User user = new User()
{
FullName = newUserName,
ID = Guid.NewGuid()
};
db.Users.InsertOnSubmit(user);
db.SubmitChanges();
}
return newUserName;
}
AddUser doesn't return anything.
AddUser is written as a method, not a class. Your test attempts to call it like a method, but the method is void, which does not return a value.
Simply speaking you can't assign void to string.
To make it work you can do in 2 ways:
make your method AddUser return string type or add extra parameter to your method and use keyword out for this parameter
hope it help.
Related
So I am trying again using a different controller to test a Cocoa desktop application using NUnit and Moq. The problem is, even after the .add() operation, I still don't have what I just added using the mock. More exactly, this is how I do the mock:
User user = new User
{
email = "test#gmail.com",
password = "1",
firstName = "Test",
lastName = "Test"
};
List<User> dataSource = new List<User>();
var userServiceMock = new Mock<IUserService>(MockBehavior.Strict);
userServiceMock.Setup(x => x.add(It.IsAny<User>()));
userServiceMock.Setup(x => x.getAllUsers()).Returns(dataSource);
var controller = new CreateAccountCoreController(userServiceMock.Object);
//act
controller.submit();
//assert
Assert.That(dataSource.Contains(user));
and in controller is this:
readonly IUserService userService;
public CreateAccountCoreController(IUserService userService)
{
this.userService = userService;
}
public void submit()
{
User user = new User
{
email = "test#gmail.com",
password = "1234",
firstName = "Test",
lastName = "Test",
};
userService.add(user);
List<User> users = userService.getAllUsers();
/*users it is empty here..*/
}
So my test always fails because the list of Users it is empty even after .add operation. Can you help please?
There is no place where you fill dataSource collection and you configure your mock to return it from getAllUsers() mock. So you will always get an empty collection from a method.
Use Callback() method to configure expected behavior:
userServiceMock.Setup(x => x.add(It.IsAny<User>())).Callback((User u) => dataSource.Add(u));
The second problem may be in comparing users in Contains() method. You need to tell Contains what makes two users equal. By default it will use ReferenceEquals which will only call two objects equal if they are the same instance.
Either override Equals and GetHashCode in your User class or define an IEqualityComparer<User> class and pass that to Contains.
If two Users that have the same email are "equal" then the implementation is pretty straightforward:
public override bool Equals(object o)
{
if(o.GetType() != typeof(User))
return false;
return this.email == ((User)o).email;
}
public override int GetHashCode()
{
return email.GetHashCode();
}
You can read more about value equality for a type.
I have a class with a method that returns an object of type User
public class CustomMembershipProvider : MembershipProvider
{
public virtual User GetUser(string username, string password, string email, bool isApproved)
{
return new User()
{
Name = username
,Password = EncodePassword(password)
,Email = email
,Status = (isApproved ? UsuarioStatusEnum.Ativo : UsuarioStatusEnum.ConfirmacaoPendente)
// ...
};
}
// ..
}
User is a domain object. Note the Id property with setter as protected:
public class User : IAuditable, IUser
{
public virtual int Id { get; protected set; }
public virtual string Name { get; set; }
public virtual string Email { get; set; }
public virtual UsuarioStatusEnum Status { get; set; }
public virtual string Password { get; set; }
}
Id is protected because it is generated by the database.
Test project
In my Test project I have a Fake repository with a method Store to save/update the object:
public void Store(T obj)
{
if (obj.Id > 0)
_context[obj.Id] = obj;
else
{
var generateId = _context.Values.Any() ? _context.Values.Max(p => p.Id) + 1 : 1;
var stubUser = Mock.Get<T>(obj); // In test, will always mock
stubUser.Setup(s => s.Id).Returns(generateId);
_context.Add(generateId, stubUser.Object);
}
}
In CustomMembershipProvider I have public override MembershipUser CreateUser method that calls the GetUser to create a User.
This way, all I have to do is mock the GetUser method so that the repository can generate the Id
var membershipMoq = new Mock<CustomMembershipProvider>();
membershipMoq.CallBase = true;
membershipMoq
.Setup(p => p.GetUser(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()))
.Returns<string, string, string, bool>( (username, password, email, isAproved) => {
var moqUser = new Mock<User>();
moqUser.Object.Name = username;
moqUser.Object.Password = password;
moqUser.Object.Email = email;
moqUser.Object.Status = (isAproved ? UsuarioStatusEnum.Ativo : UsuarioStatusEnum.ConfirmacaoPendente);
return moqUser.Object;
});
_membershipProvider = membershipMoq.Object;
Problem
In theory everything is correct. When CreateUser call 'GetUser' to create a user, the user will return Mock filled;
[TestMethod]
public void CreateUser_deve_criar_usuario_no_repositorio()
{
// Act
MembershipCreateStatus status;
var usr = _membershipProvider.CreateUser(
_fixture.Create<string>(),
_fixture.Create<string>(),
_fixture.Create<string>(),
null, null, true, null,
out status);
// usr should have name, email password filled. But not!
// Assert
status.Should().Be(MembershipCreateStatus.Success);
}
The problem is that Email, Name, Password are empty (with default values)!
The way you prepare the mocked user is the problem.
moqUser.Object.Name = username;
will not set the name, unless you have setup the mock properly.
Try this before assigning values to properties:
moqUser.SetupAllProperties();
This method will prepare all properties on the mock to be able to record the assigned value, and replay it later (i.e. to act as real property).
You can also use SetupProperty() method to set up individual properties to be able to record the passed in value.
Another approach is:
var mockUser = Mock.Of<User>( m =>
m.Name == "whatever" &&
m.Email == "someone#example.com");
return mockUser;
I think you are missing purpose of mocking. Mocks used to mock dependencies of class you are testing:
System under test (SUT) should be tested in isolation (i.e. separate from other units). Otherwise errors in dependencies will cause your SUTs tests to fail. Also you should not write tests for mocks. That gives you nothing, because mocks are not production code. Mocks are not executed in your application.
So, you should mock CustomMembershipProvider only if you are testing some unit, which depends on it (BTW it's better to create some abstraction like interface ICustomMembershipProvider to depend on).
Or, if you are writing tests for CustomMembershipProvider class, then it should not be mocked - only dependencies of this provider should be mocked.
Specifies that the all properties on the mock should have "property behavior",
meaning that setting their value will cause them to be saved and later returned when the properties is requested.
(This is also known as "stubbing".)
The default value for each property will be the one generated as specified by the
property for the mock.
mock.SetupAllProperties();
I have in model.store my user defined function, but i can't import in "Function Import".
I tryed to use this syntax:
public class dbFunction
{
[EdmFunction("MyModel.Store", "FN_GETPARVALUE")]
public static string FN_GETPARVALUE(decimal ditta, string par, string retIfNull)
{
throw new NotSupportedException("Direct calls are not supported.");
}
}
but I can't call directly like this:
CommonRepository pr = new CommonRepository();
var test = pr.parametriDittaGetValue(Near_UserDitta, "PRODGESCOL", "");
How can I resolve my Problem?
Thanks
Apologies in advance as I'm fairly new to this so imagine this is be being a fool.
Anyway, I looking to pass individual comma delimited data into fields/variables. I am using FileHelpers and have it working and passing back data but my C# skills now fail me.
The CSV Data is:
Tom, Password
Two, PassTwo
Three, PassThree
And the code I have is :
[DelimitedRecord(",")]
public class UserDetailsLogin
{
FileHelperEngine engine = new FileHelperEngine(typeof(UserDetails));
[Test]
public void TestData()
{
string User1;
string User2;
string User3;
string Password1;
UserDetails[] res = engine.ReadFile("TestData.csv") as UserDetails[];
foreach (UserDetails user in res)
{
User1 = user.UserName;
Console.WriteLine(User1);
}
}
}
[DelimitedRecord(",")]
public class UserDetails
{
public string UserName;
public string Password;
}
Which, for the purpose of checking writes to console:
Tom
Two
Three
How would I be able to pass individual data to variables e.g:
User1 = "Tom"
Password1 = "Password"
User2 = "Two" etc etc..
Neither your question nor your code is very clear.
I think you are asking how to verify the values you have read in to the UserDetails array, in which case you can use the following test:
[TestFixture]
public class UserDetailsTests
{
[Test]
public void TestData()
{
FileHelperEngine engine = new FileHelperEngine(typeof(UserDetails));
UserDetails[] res = engine.ReadFile("TestData.csv") as UserDetails[];
Assert.AreEqual(res[0].UserName, "User 1");
Assert.AreEqual(res[0].Password, "Password 1");
Assert.AreEqual(res[1].UserName, "User 2");
Assert.AreEqual(res[2].UserName, "User 3");
}
}
If I have a controller like this:
[HttpPost]
public JsonResult FindStuff(string query)
{
var results = _repo.GetStuff(query);
var jsonResult = results.Select(x => new
{
id = x.Id,
name = x.Foo,
type = x.Bar
}).ToList();
return Json(jsonResult);
}
Basically, I grab stuff from my repository, then project it into a List<T> of anonymous types.
How can I unit-test it?
System.Web.Mvc.JsonResult has a property called Data, but it's of type object, as we expected.
So does that mean if I want to test that the JSON object has the properties I expect ("id", "name", "type"), I have to use reflection?
EDIT:
Here's my test:
// Arrange.
const string autoCompleteQuery = "soho";
// Act.
var actionResult = _controller.FindLocations(autoCompleteQuery);
// Assert.
Assert.IsNotNull(actionResult, "No ActionResult returned from action method.");
dynamic jsonCollection = actionResult.Data;
foreach (dynamic json in jsonCollection)
{
Assert.IsNotNull(json.id,
"JSON record does not contain \"id\" required property.");
Assert.IsNotNull(json.name,
"JSON record does not contain \"name\" required property.");
Assert.IsNotNull(json.type,
"JSON record does not contain \"type\" required property.");
}
But I get a runtime error in the loop, stating "object does not contain a definition for id".
When I breakpoint, actionResult.Data is defined as a List<T> of anonymous types, so I figure if I enumerate through these, I can check the properties. Inside the loop, the object does have a property called "id" - so not sure what the issue is.
I know I'm a bit late on this guys, but I found out why the dynamic solution wasn't working:
JsonResult returns an anonymous object and these are, by default, internal, so they need to be made visible to the tests project.
Open your ASP.NET MVC application project and find AssemblyInfo.cs from folder called Properties. Open AssemblyInfo.cs and add the following line to the end of this file.
[assembly: InternalsVisibleTo("MyProject.Tests")]
Quoted from: http://weblogs.asp.net/gunnarpeipman/archive/2010/07/24/asp-net-mvc-using-dynamic-type-to-test-controller-actions-returning-jsonresult.aspx
I thought it would be nice to have this one for the record. Works like a charm
RPM, you look to be correct. I still have much to learn about dynamic and I cannot get Marc's approach to work either. So here is how I was doing it before. You may find it helpful. I just wrote a simple extension method:
public static object GetReflectedProperty(this object obj, string propertyName)
{
obj.ThrowIfNull("obj");
propertyName.ThrowIfNull("propertyName");
PropertyInfo property = obj.GetType().GetProperty(propertyName);
if (property == null)
{
return null;
}
return property.GetValue(obj, null);
}
Then I just use that to do assertions on my Json data:
JsonResult result = controller.MyAction(...);
...
Assert.That(result.Data, Is.Not.Null, "There should be some data for the JsonResult");
Assert.That(result.Data.GetReflectedProperty("page"), Is.EqualTo(page));
I'm a bit late to the party, but I created a little wrapper that lets me then use dynamic properties. As of this answer I've got this working on ASP.NET Core 1.0 RC2, but I believe if you replace resultObject.Value with resultObject.Data it should work for non-core versions.
public class JsonResultDynamicWrapper : DynamicObject
{
private readonly object _resultObject;
public JsonResultDynamicWrapper([NotNull] JsonResult resultObject)
{
if (resultObject == null) throw new ArgumentNullException(nameof(resultObject));
_resultObject = resultObject.Value;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (string.IsNullOrEmpty(binder.Name))
{
result = null;
return false;
}
PropertyInfo property = _resultObject.GetType().GetProperty(binder.Name);
if (property == null)
{
result = null;
return false;
}
result = property.GetValue(_resultObject, null);
return true;
}
}
Usage, assuming the following controller:
public class FooController : Controller
{
public IActionResult Get()
{
return Json(new {Bar = "Bar", Baz = "Baz"});
}
}
The test (xUnit):
// Arrange
var controller = new FoosController();
// Act
var result = await controller.Get();
// Assert
var resultObject = Assert.IsType<JsonResult>(result);
dynamic resultData = new JsonResultDynamicWrapper(resultObject);
Assert.Equal("Bar", resultData.Bar);
Assert.Equal("Baz", resultData.Baz);
Here's one I use, perhaps it is of use to anyone. It tests an action that returns a JSON object for use in clientside functionality. It uses Moq and FluentAssertions.
[TestMethod]
public void GetActivationcode_Should_Return_JSON_With_Filled_Model()
{
// Arrange...
ActivatiecodeController activatiecodeController = this.ActivatiecodeControllerFactory();
CodeModel model = new CodeModel { Activation = "XYZZY", Lifespan = 10000 };
this.deviceActivatieModelBuilder.Setup(x => x.GenereerNieuweActivatiecode()).Returns(model);
// Act...
var result = activatiecodeController.GetActivationcode() as JsonResult;
// Assert...
((CodeModel)result.Data).Activation.Should().Be("XYZZY");
((CodeModel)result.Data).Lifespan.Should().Be(10000);
}
I extend the solution from Matt Greer and come up with this small extension:
public static JsonResult IsJson(this ActionResult result)
{
Assert.IsInstanceOf<JsonResult>(result);
return (JsonResult) result;
}
public static JsonResult WithModel(this JsonResult result, object model)
{
var props = model.GetType().GetProperties();
foreach (var prop in props)
{
var mv = model.GetReflectedProperty(prop.Name);
var expected = result.Data.GetReflectedProperty(prop.Name);
Assert.AreEqual(expected, mv);
}
return result;
}
And i just run the unittest as this:
- Set the expected data result:
var expected = new
{
Success = false,
Message = "Name is required"
};
- Assert the result:
// Assert
result.IsJson().WithModel(expected);
My solution is to write the extension method:
using System.Reflection;
using System.Web.Mvc;
namespace Tests.Extensions
{
public static class JsonExtensions
{
public static object GetPropertyValue(this JsonResult json, string propertyName)
{
return json.Data.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public).GetValue(json.Data, null);
}
}
}
If in the test you know what exactly the Json data result should be then you can just do something like this:
result.Data.ToString().Should().Be(new { param = value}.ToString());
P.S. This would be if you had used FluentAssertions.Mvc5 - but it shouldn't be hard to convert it to whatever testing tools you use.
This is how I assert it
foreach (var item in jsonResult.Data as dynamic) {
((int)item.Id).ShouldBe( expected Id value );
((string)item.name).ShouldBe( "expected name value" );
}
You can convert the value property of the JsonResult into an instance of a known type and then simply access it's properties.
public static class JsonResultExtensions
{
public static T ExtractType<T>(this JsonResult result)
{
var resultAsJson = JsonSerializer.Serialize(result.Value);
return JsonSerializer.Deserialize<T>(resultAsJson);
}
}
below is an example of the use of the extension method:
MyModel model = jsonResult.ExtractType<MyModel>();
Assert.True(model.Success);