vendredi 1 juillet 2016

How to add mock PaginatedList to List.addAll?

I have to add the PaginatedQueryList from to secondList which comes from dynamoDbMapper.query for testing. How can I achieve it?

List exampleList = secondList.addAll(dynamoDbMapper.query(MyDAOClass.class, queryExpression));

I tried to mock the PaginatedQueryList but am getting null pointer exception because elements in mocked PaginatedQueryList is empty.

Any suggestions please?

Angular 2 RC how to unit test an observable

I am writing some tests for an angular 2 RC application and I'm having some issues with the testing of observables. I mocked up the method setting it's type as observable but when the unit being tested tries to subscribe to the mocked observable I get an error 'Cannot read property 'subscribe' of undefined'

I'm testing my DashboardComponent, which injects a model3DService and calls model3DService.get3DModels() which is an observable that does an http request and returns an array of 3D model objects.

Here's some sample code:

Dashboard Component

import { Model3DService } from '../../services/model3D/model3D.service';
import { ProjectService } from '../../services/project/project.service';

@Component({
  selector: 'cmg-dashboard',
  styles: [require('./css/dashboard.scss')],
  template: require('./dashboard.html')
})
export class DashboardComponent implements OnInit {
  constructor(
    private projectService: ProjectService,
    private model3DService: Model3DService
  ) { }

  ngOnInit (): void {
    this.model3DService.get3DModels().subscribe((res: any[]) => {
      this.findProjects(res);
      this.models = res;
      this.projectService.isProjectSelected = true;
      this.createProject(res[0]);
    });
  }
}

Model3DService

@Injectable()
export class Model3DService {
 private models: any[] = [];

 public get3DModels (): Observable<any> {
    return this.http.get('../../../json/3DModel.json')
    .map(( res: Response ) => {
      this.models = res.json();
      return this.models;
    });
  }
}

Okay now that we have the under test heres the test I'm writing.

Dashboard Component Spec

class MockModel3DService {
  public get3DModels(): Observable<any> {
    return;
  }
}

describe('Dashboard Component', () => {
  beforeEachProviders(() => {
    return [
      DashboardComponent,
      provide(ProjectService, {
        useClass: MockProjectService
      }),
      provide(Model3DService, {
        useClass: MockModel3DService
      })
    ];
  });

  describe('ngOnInit', () => {
    it('should call model3DService.get3DModels on init', (inject([DashboardComponent], (dashboardComponent: DashboardComponent, model3DService: MockModel3DService) => {
      dashboardComponent.ngOnInit();
      expect(model3DService.get3DModels).toHaveBeenCalled();
    })));
  });
});

Can I put a table valued function in a DataSourceAttribute?

Microsoft's [DataSource(...)] lets you put in a name of a table as a string to supply data to your unit test. I want to generate data with dynamic sql, and believe the best way to do this would be with a tvf, though I'm open to suggestions. When I try:

[DataSource("System.Data.SqlClient", CONN, "tvf(10)", DataAccessMethod.Sequential]

I get an invalid object name 'tvf(10)' error. I can only assume Microsoft is putting [brackets] around my tvf(10) and totally killing its tvf-ness. Is there a way around this?

Angular 2 RC Unit Testing how to mock injections

I am trying to write some unit tests for an application I have been building but I'm running into issues with mocking injections on the various components/services. I've been reading articles and trying various things for a few hours now but so far been unable to find any examples of the correct way to configure the mocks, however I appear to be close...

I have the following code for my test for a DashboardComponent:

import {
  beforeEach,
  beforeEachProviders,
  describe,
  expect,
  inject,
  injectAsync,
  it
} from '@angular/core/testing';
import { provide } from '@angular/core';
import { Observable } from 'rxjs/Observable';

import { DashboardComponent } from './dashboard.component';
import { ProjectService } from '../../services/project/project.service';
import { Model3DService } from '../../services/model3D/model3D.service';

class MockProjectService {
  public find (model: any): void {}
}

class MockModel3DService {
  public get3DModels (): Observable<any> {
    return;
  }
}

fdescribe('Dashboard Component', () => {
  beforeEachProviders(() => {
    return [
      DashboardComponent,
      provide(ProjectService, {
        useClass: MockProjectService
      }),
      provide(Model3DService, {
        useClass: MockModel3DService
      })
    ];
  });

  describe('foo', () => {
    it('should do stuff', (inject([DashboardComponent], (dashboardComponent: DashboardComponent) => {
      dashboardComponent.easyTest();
      expect(dashboardComponent.foo).toEqual('foobar');
    })));
  });

  describe('ngOnInit', () => {
    it('should call model3DService.get3DModels on init', (inject([DashboardComponent, Model3DService], (dashboardComponent: DashboardComponent, model3DService: MockModel3DService) => {
      dashboardComponent.ngOnInit();
      expect(model3DService.get3DModels()).toHaveBeenCalled();
    })));
  });
});

A couple things to note:

In the examples I've found they extend the real class when they create a mock class. i.e. class MockProjectService { would be class MockProjectService extends ProjectService { however that appears to inject the actual class into the component because I then get errors saying I need to inject every service that is injected into ProjectService, and then inject every injection that each of those injections have, so on and so forth. Obviously that isn't what I want as the tests for DashboardComponent shouldn't care about the actual code behind anything injected into DashboardComponent or any of its dependencies.

By removing the extends bit of code I was able to get my code to run a simple test where I call a method on DashboardComponent and expect a string to have been updated, it works! I thought I had this nailed, but then I tried to write a test that calls a method on a mocked service, but for some reason the mocked service is empty! :( In the second test above you'll notice I expect model3DService.get3DModels to have been called, however I get an error that get3DModels is undefined. I console logged the value of model3DService in my component on the line above where it tries to use model3DService.get3DModels and the log shows me that model3DService is set to MockModel3DService{} which is missing the method I defined inside MockModel3DService in my test...

How are you all setting up your mocks so you don't have to go down an endless rabbit hole of injections?

Issues Unit Testing EF & ASP.NET Identity - various exceptions from EF & FakeItEasy

Background:

I am working on getting some experience in unit testing, as per my new employer's strict unit testing requirements, but unit testing as a whole is new to me. I have had a TON of issues trying to test any of the methods that make use of ASP.NET Identity, due to the reliance on HttpContext.Current.GetOwinContext().Authentication and HttpContext.Current.GetOwinContext().GetUserManager

Now, this current project has not fully taken advantage of Interfaces and Dependency Injection so far, but as a part of incorporating our organization's Active Directory system into our Identity Database (creating a row in the Users table for someone when they log in with valid Active Directory credentials, and then using the Identity database for them from then on), I have been working on retrofitting our Identity side of things with Interfaces and Ninject, and adding FakeItEasy to our test unit test projects.

This does mean that we are currently generating tests that use the actual databases themselves as opposed to faking things. We know this is a bad practice and it was done simply for the sake of not overloading us new guys' minds while we work on our first real project. We have worked out (most/all) of the kinks this causes and our tests clean things up when they are finished.

Question 1:
I am running into a peculiar issue while trying to unit test the following method:

public bool ResetPassword(User user)
    {
        if (!user.EmailConfirmed) return false;

        user.RequirePasswordReset = true;
        string randomGeneratedPassword = GenerateRandomPassword(20); // defined at end of class
        user.PasswordHash = hash.HashPassword(randomGeneratedPassword);

        if (!UpdateUser(user)) return false;

        string message = "We have received a request to reset your password. <br /><br />" +
            "Your new password is shown below. <br /><br />" +
            $"Your new password is: <br />{randomGeneratedPassword}<br /><br />" +
            "This password is only valid for one login, and must be changed once it is used. <br /><br /><br /><br />" +
            "Server<br />AmTrust Developer University";

        SendFormattedEmail(user.Email, user.FullName, message, "Your password has been reset");
        return true;
    }

The test I have written so far to do so (with the testcases omitted) is:

public bool ResetPasswordTests(bool emailConfirmed)
    {
        //arrange
        _user = new User()
        {
            Email = "ttestingly@test.com",
            EmailConfirmed = emailConfirmed,
            FirstName = "Test",
            isActive = true,
            isActiveDirectoryAccount = false,
            LastName = "Testingly",
            PasswordHash = _hash.HashPassword("secret1$"),
            RequirePasswordReset = false,
            UserName = "ttestingly"
        };

        string hashedPass = _user.PasswordHash;

        _identityContext.Users.Add(_user);
        _identityContext.SaveChanges();

        //Suppress the email sending bit!
        A.CallTo(() => _userBusinessLogic_Testable.SendFormattedEmail(null, null, null, null, null))
        .WithAnyArguments()
        .DoesNothing();

        //act
        bool result = _userBusinessLogic_Testable.ResetPassword(_user);

        //assert
        Assert.That(result);
        Assert.That(_user.PasswordHash != hashedPass);
        Assert.That(_user.RequirePasswordReset);
        return result;
    }

Running this test (for all of its various TestCases) returns the following exception:

System.NotSupportedException: Model compatibility cannot be checked because the database does not contain model metadata. Model compatibility can only be checked for databases created using Code First or Code First Migrations.

This is caused by _identityContext.Users.Add(_user);

Everything I've seen about this issue indicates that it is caused by an open connection to the database while code is run trying to connect to that database, which I don't think is the case, or from trying to have EF manage a pre-existing database (which is not the case: I have deleted my databases multiple times between tests to try to verify this).

Note: Currently all of our team's databases are just localhost databases, so there's no one else messing with my stuff.

I have seen an example of this where the solution was to change the connection string, however this issue ONLY happens in Unit Testing - I have verified that while running, everything on the application works as expected prior to any changes I have made to incorporate Interfaces, Ninject, and Active Directory - so I do not think the connection string itself is the issue, but here is the relevant connection string (they are proper XML but I'm not sure how to get them to show up properly on Stack Overflow, so I removed all of the braces):

connectionStrings
add name="ADUUserDB" providerName="System.Data.SqlClient" connectionString="Data Source=localhost\sql2014;Initial Catalog=ADUUserDB;Integrated Security=True;Connect Timeout=15;Encrypt=False;TrustServerCertificate=False; MultipleActiveResultSets=True"
/connectionStrings

Question 2:
On the other side of the application, I am attempting to test one of my Controllers (which are currently not unit tested at all, due to not having FakeItEasy or any alternative prior to now), and all of my attempted tests are throwing the following exception:

FakeItEasy.Configuration.FakeConfigurationException:
The current proxy generator can not intercept the specified method for the following reason:
- Extension methods can not be intercepted since they're static.

This occurs at the very first attempted A.CallTo() I have written for the following test:

    public async Task LoginTests(bool activeDirectory, string returnUrl, bool emailConfirmed, bool requirePasswordReset)
    {
        if (activeDirectory) requirePasswordReset = false;
        //arrange
        _user = new User()
        {
            Email = activeDirectory ? "99999" : "ttestingly@test.com",
            EmailConfirmed = emailConfirmed,
            FirstName = "Test",
            isActive = true,
            isActiveDirectoryAccount = activeDirectory,
            LastName = "Testingly",
            RequirePasswordReset = requirePasswordReset,
            PasswordHash = _hash.HashPassword("secret1$"),
            UserName = "ttestingly"
        };

        if (!activeDirectory)
        {
            A.CallTo(() => _userBusinessLogic.GetUsers(null, null, null, null, null, null, null)
                .Single())
                .WithAnyArguments()
                .Returns(_user);
        }
        else
        {
            A.CallTo(() => _userBusinessLogic.GetUsers(null, null, null, null, null, null, null)
                .Single())
                .WithAnyArguments()
                .Throws(new ApplicationException());

            A.CallTo(() => _userBusinessLogic.CreateActiveDirectoryAccount(99999, "secret1$", false))
                .Returns(true);
        }

        A.CallTo(() => _userBusinessLogic.CreateClaimsIdentityForUser(null, false))
            .WithAnyArguments()
            .Returns(true);

        LoginViewModel model = new LoginViewModel()
        {
            UserName = _user.UserName,
            Password = "secret1$",
            RememberMe = false,
        };

        //act
        ActionResult result = await _controller.Login(model, returnUrl);

        //assert
        if (returnUrl != null) Assert.That(result is RedirectResult);

        else if (activeDirectory || emailConfirmed) Assert.That(result is ViewResult);

        else if (requirePasswordReset) Assert.That(result is RedirectToRouteResult);
    }

The variable that we are calling the method from is private IUserBusinessLogic _userBusinessLogic = A.Fake<IUserBusinessLogic>();

As you can see, it is a method signature that is defined as part of an Interface, shown below:

public interface IUserBusinessLogic
{
    HttpContext CurrentContext { get; }

    bool ChangePassword(string userId, string currentPassword, string newPassword, out List<string> errors);

    Task<bool?> CreateActiveDirectoryAccount(uint adUserName, string password, bool RememberMe = false);
    Task<bool> CreateClaimsIdentityForUser(User user, bool rememberMe = false);
    Task<bool> CreateIdentityAsync(User user, string authenticationType, bool rememberMe = false);

    IList<DbValidationError> CreateUser(User user, bool privateExamTaken, bool privateExamDeadline, bool publicExamTaken, bool takenExamGraded, bool takenExamDeadline);
    User FindOrGenerateUser(string Email, string FirstName, string LastName);
    IList<User> GetUsers(IList<string> UserIds = null, IList<long> StudentIds = null, 
        string firstNameText = null, string lastNameText = null, 
        string userNameText = null, string emailText = null, 
        bool? isActive = default(bool?));

    void Logout();
    void SendEmail(string message, string userEmail, string subject = "Password Reset Request", string replyTo = null);
    void SendFormattedEmail(string Email, string FullName, string Message, string Subject, string replyTo = null);
    void SendNotificationEmail(AmtrustDeveloperUniversityUser student, NotificationOptions notification, ExamSchedule schedule);

    Task<bool> SyncUserPassword_With_ActiveDirectory(User user, string Password, bool RememberMe = false);

    bool ResetPassword(User user);
    bool UpdateUser(User user);

    ApplicationException UpdateUserActiveStatus(string userId, bool activeStatus);
    Task<IdentityResult> ValidateAsync(string password);

    bool ValidateActiveDirectoryCredentials(uint username, string password, out UserPrincipal principal);
}

I have done some reading and found that Fakes can only be made of Virtual method calls, but given that I am faking an interface, it should be the case that this issue never crops up - if it were only the .CreateClaimsIdentityForUser() call, I could at least understand why this was happening (as that method call in the injected class uses UserManager.CreateIdentityAsync) - but faking this and telling it what I want it to return shouldn't be an issue, I would think.

The ninject bindings I have defined so far are: private void AddBindings(IKernel kernel) { kernel.Bind().To(); kernel.Bind().To(); kernel.Bind().To(); }

...I've run out of characters to use so if you need more information just ask. Any help is appreciated, be it something I need to go learn about, clarification for what is meant by these errors, or a better method of testing the code I am trying to test.

Integration Testing with Entity Framework

We are using EF 6.0 and are trying to figure out how best to simulate a physical database with a mocked in memory database. We have attempted using the Moq approach in the article Mocking EF 6.0 and higher

However, this does not support something like the following:

var person = dbCtx.Persons.Include(x => x.Pets).Where(x => x.ID = 1).Single();
person.Pets.Add(new Pet{ Name = "Spike", Type = "Dog" });
dbCtx.Save();

The problems with the above are as follows:

  1. Mocking the EF Context supports native IEnumerable Linq statements. Include is not part of this set. You can make include work by serializing all values on the root entity, but this doesn't adequately simulate a real world situation. In a real database with LazyLoading turned off, if you did not specify an include then the navigation property of Pets would be null. This is important.
  2. Due to the issue in #1, the IDbSet Pets never gets the newly added pet added to it as the Pet "Spike" is only added to the Person entity that was retrieved. So in post state checking you are unable to check the pets collection to ensure the correct values were entered or updated.

Any insight here would be greatly appreciated.

cassandraunit throws Dataset not found error

I am using cassandra-unit 3.0.0.1 from here but it is throwing dataset not found error

@Rule
public CassandraCQLUnit cassProvider = new CassandraCQLUnit(new ClassPathCQLDataSet("simple.cql","keyspaceNameToCreate"));

is there any other plugins i need to use or is it a bug in cassandra-unit?