I have created coded activity and now I want to unit test it, but I do not know how.
Any example will be appreciated.
My simple example is below.
public sealed class ParameterActivity : CodeActivity
{
public InArgument<int> Argument1 { get; set; }
public InArgument<int> Argument2 { get; set; }
public OutArgument<int> Result { get; set; }
protected override void Execute(CodeActivityContext context)
{
var a = context.GetValue(Argument1);
var b = context.GetValue(Argument2);
context.SetValue(Result, a + b);
}
}
First of all, in case your activity returns a single value, just inherit from CodeActivity<TResult> and easily override Execute() with TResult as return type. Moreover, you've already available an OutArgument<TResult> Result.
public sealed class ParameterActivity : CodeActivity<int>
{
public InArgument<int> Argument1 { get; set; }
public InArgument<int> Argument2 { get; set; }
protected override int Execute(CodeActivityContext context)
{
var a = Argument1.Get(context);
var b = Argument2.Get(context);
return a + b;
}
}
That being said, WorkflowInvoker is the way to go to unit test almost all your activities. Taking above custom code activity as example:
[TestFixture]
public sealed class ParameterActivityTests
{
[Test]
public void ParameterActivity_Test()
{
var activity = new ParameterActivity();
var input1 = new Dictionary<string, object>
{
{ "Argument1", 10 },
{ "Argument2", 5 }
};
var input2 = new Dictionary<string, object>
{
{ "Argument1", -13 },
{ "Argument2", 3 }
};
var output1 = WorkflowInvoker.Invoke<int>(activity, input1);
var output2 = WorkflowInvoker.Invoke<int>(activity, input2);
Assert.That(output1, Is.EqualTo(15));
Assert.That(output2, Is.EqualTo(-10));
}
}
Rather than WorkflowInvoker you can also use WorkflowApplication but for unit testing that doesn't seem at all necessary when you just want to quickly invoke short-lived workflows for them to do "their thing" and return. Unless you want to test more elaborate stuff like asynchronous workflows and/or bookmarks.
You'll also want to check Microsoft.Activities.UnitTesting.
Related
I am writing test for Web API application written in .NET CORE 3.1. I am using xUnit, AutoFixture & Moq for testing. I have a class that creates a new school instance in the database using Entity Framework/ DbContext. My question is how to mock dbContext & save changes, further my School DataModel has one: many relationships with SchoolBranch DataModel. I have followed this tutorial https://learn.microsoft.com/en-us/ef/ef6/fundamentals/testing/mocking
Error
Message:
Moq.MockException :
Expected invocation on the mock once, but was 0 times: m => m.Add<School>(It.IsAny<School>())
Performed invocations:
Mock<SchoolDbContext:1> (m):
No invocations performed.
Stack Trace:
Mock.Verify(Mock mock, LambdaExpression expression, Times times, String failMessage)
Mock`1.Verify[TResult](Expression`1 expression, Times times)
CreateSchoolCommandTest.ExecuteMethod_ShouldReturnNewGuidId_IfSuccess() line 50
School
public class School
{
public School()
{
this.SchoolBranches = new HashSet<SchoolBranch>();
}
public Guid SchoolID { get; set; }
public string Name { get; set; }
public ICollection<SchoolBranch> SchoolBranches { get; set; }
}
SchoolBranch
public class SchoolBranch
{
public SchoolBranch()
{
}
public Guid SchoolBranchID { get; set; }
public Guid SchoolID { get; set; }
public string Address { get; set; }
public int PhoneNumber { get; set; }
public School School { get; set; }
}
CreateSchool Class
public class CreateSchool : BaseCommand<Guid>, ICreateSchool
{
public SchoolDto SchoolDtos { get; set; }
public CreateSchool(IAppAmbientState appAmbient) : base(appAmbient) { }
public override Guid Execute()
{
try
{
var schoolId = Guid.NewGuid();
List<SchoolBranch> schoolBranches = new List<SchoolBranch>();
foreach(var item in SchoolDtos.SchoolBranchDtos)
{
schoolBranches.Add(new SchoolBranch()
{
SchoolBranchID = Guid.NewGuid(),
SchoolID = schoolId,
Address = item.Address,
PhoneNumber = item.PhoneNumber
});
}
var school = new School()
{
SchoolID = schoolId,
Name = SchoolDtos.Name,
SchoolBranches = schoolBranches
};
schoolDbContext.Schools.Add(school);
schoolDbContext.SaveChanges();
return school.SchoolID;
}
catch(Exception exp)
{
appAmbientState.Logger.LogError(exp);
throw;
}
}
}
Test Class
public class CreateSchoolCommandTest
{
private readonly ICreateSchool sut;
private readonly Mock<IAppAmbientState> appAmbientState = new Mock<IAppAmbientState>();
[Fact]
public void ExecuteMethod_ShouldReturnNewGuidId_IfSuccess()
{
//Arrange
var fixture = new Fixture();
var schoolDtoMock = fixture.Create<SchoolDto>();
var schoolDbSetMock = new Mock<DbSet<School>>();
var schoolBranchDbSetMock = new Mock<DbSet<SchoolBranch>>();
var schoolDbContextMock = new Mock<SchoolDbContext>();
//schoolDbSetMock.Setup(x => x.Add(It.IsAny<School>())).Returns((School s) => s); // this also did not work
schoolDbContextMock.Setup(m => m.Schools).Returns(schoolDbSetMock.Object);
//Act
sut.SchoolDtos = schoolDtoMock;
var actualDataResult = sut.Execute();
// Assert
Assert.IsType<Guid>(actualDataResult);
schoolDbContextMock.Verify(m => m.Add(It.IsAny<School>()), Times.Once());
schoolDbContextMock.Verify(m => m.SaveChanges(), Times.Once());
}
BaseCommand (DbContext is created here)
public abstract class BaseCommand<T>
{
protected SchoolDbContext schoolDbContext;
protected IAppAmbientState appAmbientState { get; }
public BaseCommand(IAppAmbientState ambientState)
{
this.schoolDbContext = new SchoolDbContext();
this.appAmbientState = ambientState;
}
public abstract T Execute();
}
For fix Error
You made just a little mistake. Insted of
schoolDbContextMock.Verify(m => m.Add(It.IsAny<School>()), Times.Once());
schoolDbContextMock.Verify(m => m.SaveChanges(), Times.Once());
You should have
schoolDbSetMock.Verify(m => m.Add(It.IsAny<School>()), Times.Once());
schoolDbContextMock.Verify(m => m.SaveChanges(), Times.Once());
Because you use method Add() on schoolDbContext.Schools not on schoolDbContext
For injecting dbContext
Your BaseCoommand class constructor should look like this:
public BaseCommand(IAppAmbientState ambientState, SchoolDbContext schoolDbContext)
{
this.schoolDbContext = schoolDbContext;
this.appAmbientState = ambientState;
}
Your CreateSchool class constructor:
public CreateSchool(IAppAmbientState appAmbient, SchoolDbContext schoolDbContext) : base(appAmbient, schoolDbContext) { }
And next in test you should initialize CreateSchool in test like this:
var sut = new CreateSchool(ambientState, schoolDbContextMock.Object);
And it will work
I am trying to write some unit tests for my account controller web apis which make use of UserManager but I keep receiving null on the line in the title in the following section:
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
I have tried so many different ways to fix this as I have read that I need to Mock some of the parts of ApplicationUser but have not managed to get any of them to fix my problem. Below is some of the code I have implemented following a tutorial to unit test:
public interface IStoreAppContext : IDisposable
{
//IDbSet<User> Users { get; }
DbSet<User> u { get; }
DbSet<SportProgram> SportContext { get; set; }
int SaveChanges();
void MarkAsModified(User item);
}
}
The api I am trying to unit test in my account controller is:
(This line below "var user..." is where the problem starts. it calls the line in the title of this question)
[Route("userProfile/{username}")]
public IHttpActionResult getUserProfile(String username)
{
var user = UserManager.FindByName(username);
if (user != null)
{
db2.MarkAsModified(user);
return Ok(user);
}
else
{
return NotFound();
}
}
Then in my TestProject I have the following context class:
class TestStoreAppContext : IStoreAppContext
{
public TestStoreAppContext()
{
this.u = new TestProductDbSet();
}
public DbSet<User> u { get; set; }
public DbSet<SportProgram> SportContext { get; set; }
public int SaveChanges()
{
return 0;
}
public void MarkAsModified(User item) { }
public void Dispose() { }
}
}
Finally in my test controller where i test the api:
[TestMethod()]
public void getUserProfileTest()
{
var context = new TestStoreAppContext();
context.u.Add(GetDemoProduct());
var controller = new AccountController(context);
var result = controller.getUserProfile("john") as OkNegotiatedContentResult<User>;
Assert.AreEqual("john", result.Content.UserName);
}
The GetDemoProduct called above:
User GetDemoProduct()
{
return new User()
{
Id = "3",
UserName = "john",
Password = "Password-1",
};
}
Can anyone point me in the right direction please?
I am getting started with Automoq. I was trying to do something like this:
mocker.GetMock<IMyObjectToTweak>();
var line = mocker.Resolve<IMyObjectToTweak>();
line.PropertyOne = .75;
line.PropertyTwo = 100;
MyCalc calc = new MyCalc();
calc.Multiply(line);
Assert.AreEqual(75, line.result);
This runs bu fails. My properties do not get set. Am I missing the idea of Automoq? What is a good resource/tutorial?
To set property with Moq (this is what Automoq uses to create mock objects) you have to use different calls, - Setup, SetupGet or SetupProperty:
var line = mocker.Resolve<IMyObjectToTweak>();
// each does the same thing - "tells" PropertyOne to return .75 upon get
line.Setup(l => l.PropertyOne).Returns(.75);
line.SetupGet(l => l.PropertyOne).Returns(.75);
line.SetupProperty(l => l.PropertyOne, .75);
I suggest expose a Result property in your Sut (System Under test)
[TestClass]
public class SomeTest : ControllerTestBase
{
[TestMethod]
public void MethodNameOrSubject_ScenarioOrCondition_ExpectedBehaviourOrReturnValue()
{
var mock = _autoMoqContainer.GetMock<IMyObjectToTweak>();
var line = _autoMoqContainer.Resolve<IMyObjectToTweak>();
mock.Setup(x => x.PropertyOne).Returns(.75);
mock.Setup(x => x.PropertyTwo).Returns(100);
MyCalc calc = new MyCalc();
calc.Multiply(line);
Assert.AreEqual(75, calc.Result);
}
}
public interface IMyObjectToTweak
{
double PropertyOne { get; set; }
int PropertyTwo { get; set; }
}
public class MyCalc
{
public double Result { get; set; }
public void Multiply(IMyObjectToTweak line)
{
Result = line.PropertyOne*line.PropertyTwo;
}
}
Not related - But read my post more on AutoMocking
http://www.dotnetcurry.com/ShowArticle.aspx?ID=767
I have a Apicontroller Which has dependency on unit of work object. How to write a test case for mocking ApiController Which has dependency on unit of work implemented in ApiController constructor.
Here is the code:
ApiController:
public class UserController : ApiController
{
public IUoW UoW { get; set; }
// GET api/user
public UserController(IUoW uow)
{
UoW = uow;
}
public IEnumerable<Users> Get()
{
return UoW.Users.Getall();
}
}
The Test case :
[TestMethod]
public void TestApiController()
{
var userManager = new Mock<IUoW>();
userManager.Setup(s => s.Users);
var controller = new UserController(userManager.Object);
var values = controller.Get();
Assert.IsNotNull(values);
}
The Users Class which has been mentioned here in UoW.Users is
public class UoW:IUoW,IDisposable
{
private MvcWebApiContext DbContext { get; set; }
protected IRepositoryProvider RepositoryProvider { get; set; }
private IRepository<T> GetStandardRepo<T>() where T : class
{
return RepositoryProvider.GetRepositoryForEntityType<T>();
}
public IRepository<Users> Users
{
get { return GetStandardRepo<Users>(); }
}
}
and the Users class itself is
[Table("UserProfile")]
public class Users
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
[DataType(DataType.PhoneNumber)]
public long Mobile { get; set; }
}
When I am trying to debug the test case , the Test case shows the object UoW.Users is null in UserController. Its obvious its not initializing through WebActivator since global.asax isnt invoked here through mock. Now how to write a successful test scenario in this context so that the WebApicontroller returns me the users object with data ?
Are you using Moq?
As I cannot see what type the UoW.Users property is I cannot demo how to mock it properly (updated IRepository) but that should be mocked and the GetAll method stubbed to return a sample list of users.
Updated
var userManager = new Mock<IUoW>();
userManager.Setup(s => s.Users).Returns(()=>
{
var userReposisitory = new Mock<IRepository<Users>>();
userReposisitory.Setup(ur => ur.GetAll()).Returns(()=> {
var listOfUsers = new List<Users>();
listOfUsers.Add(new Users { FirstName = "Example" });
return listOfUsers.AsQueryable();
});
return userReposisitory.Object;
});
var controller = new UserController(userManager.Object);
var result = controller.Get();
Assert.IsNotNull(result);
Assert.IsTrue(result.Count() > 0);
I am running on Castle's trunk, and trying to unit-test a controller-action where validation of my DTO is set up. The controller inherits from SmartDispatcherController. The action and DTO look like:
[AccessibleThrough(Verb.Post)]
public void Register([DataBind(KeyReg, Validate = true)] UserRegisterDto dto)
{
CancelView();
if (HasValidationError(dto))
{
Flash[KeyReg] = dto;
Errors = GetErrorSummary(dto);
RedirectToAction(KeyIndex);
}
else
{
var user = new User { Email = dto.Email };
// TODO: Need to associate User with an Owning Account
membership.AddUser(user, dto.Password);
RedirectToAction(KeyIndex);
}
}
public class UserRegisterDto
{
[ValidateNonEmpty]
[ValidateLength(1, 100)]
[ValidateEmail]
public string Email { get; set; }
[ValidateSameAs("Email")]
public string EmailConfirm { get; set; }
[ValidateNonEmpty]
public string Password { get; set; }
[ValidateSameAs("Password")]
public string PasswordConfirm { get; set; }
// TODO: validate is not empty Guid
[ValidateNonEmpty]
public string OwningAccountIdString { get; set; }
public Guid OwningAccountId
{
get { return new Guid(OwningAccountIdString); }
}
[ValidateLength(0, 40)]
public string FirstName { get; set; }
[ValidateLength(0, 60)]
public string LastName { get; set; }
}
The unit test looks like:
[Fact]
public void Register_ShouldPreventInValidRequest()
{
PrepareController(home, ThorController.KeyPublic, ThorController.KeyHome, HomeController.KeyRegister);
var dto = new UserRegisterDto { Email = "ff" };
home.Register(dto);
Assert.True(Response.WasRedirected);
Assert.Contains("/public/home/index", Response.RedirectedTo);
Assert.NotNull(home.Errors);
}
("home" is my HomeController instance in the test; home.Errors holds a reference to an ErrorSummary which should be put into the Flash when there's a validation error).
I am seeing the debugger think that dto has no validation error; it clearly should have several failures, the way the test runs.
I have read Joey's blog post on this, but it looks like the Castle trunk has moved on since this was written. Can someone shed some light, please?
http://www.candland.net/blog/2008/07/09/WhatsNeededForCastleValidationToWork.aspx would appear to contain an answer.