MockRestServiceServer changing request factory - resttemplate

I am unable to get my tests to run because MockRestServiceServer changes the requestfactory so doing the following doesn't work.
restTemplate.setRequestFactory(new SimpleClientHttpRequestFactory(new AcceptAllHostnameVerifier()));
mockRestServiceServer = MockRestServiceServer.createServer(restTemplate);
This is the source constructor:
public static MockRestServiceServer createServer(RestTemplate restTemplate) {
Assert.notNull(restTemplate, "'restTemplate' must not be null");
MockRestServiceServer mockServer = new MockRestServiceServer();
RequestMatcherClientHttpRequestFactory factory = mockServer.new RequestMatcherClientHttpRequestFactory();
restTemplate.setRequestFactory(factory);
return mockServer;
Is there anyway to set the request factory on MockRestServiceServer so my tests will run?

Related

Mock IRequestClient<> during Integration Testing using MassTransit

I'm trying to do integration testing against a MediatR Command whose handler depends on an IRequestClient injected into its constructor.
public class SayHelloCommand : IRequest<string>
{
}
public class SayHelloCommandHandler : IRequestHandler<SayHelloCommand, string>
{
private readonly IRequestClient<IGetProfileMessageResult> _profileClient;
public SayHelloCommandHandler(IRequestClient<IGetProfileMessageResult> profileClient)
{
_profileClient = profileClient;
}
public async Task<string> Handle(SayHelloCommand request, CancellationToken cancellationToken)
{
var profile = (await _profileClient.GetResponse<IGetProfileMessageResult>(new {ProfileId = 1})).Message;
return $"Hello {profile.FirstName}";
}
}
I've setup my test suite to use the InMemoryMassTransit but whenever I run my test it times out when it reaches the call using the IRequestClient<>. I've also tried to moq the IRequestClient to return a default response like this -
[Test]
public async Task ShouldSayHello()
{
var mockRequestClient = new Mock<IRequestClient<IGetProfileMessageResult>>();
mockRequestClient.Setup(x => x.GetResponse<IGetProfileMessageResult>(It.IsAny<Object>(), default, default)
.Result.Message).Returns(new GetProfileMessageResult
{
FirstName = "John"
});
serviceCollection.Add(new ServiceDescriptor(typeof(IRequestClient<IGetProfileMessageResult>), mockRequestClient.Object));
var result = await SendAsync(command);
result.Status.Should().BeFalse();
result.Message.Should().Contain("John");
}
but this still times out.
Is there a way I can set up the InMemoryMassTransit to return a default response when the requestclient is called?
You could use the in-memory test harness to setup a simple consumer that would respond to the request, instead of trying to mock IRequestClient. Though you should be able to mock it if you want, I just don’t know the syntax to properly configure your mock framework.
There are many samples using the test harness available, as well as all of the MassTransit unit tests.

Setting custom date formats through Jackson2ObjectMapperBuilder causing request processing to continue after exception

I have a MockMvc test for testing that a JSON payload to a controller is validated and a HTTP 400 (bad request) is rendered for org.springframework.data.mapping.PropertyReferenceException and org.springframework.http.converter.HttpMessageConversionException.
The respective exception handlers are implemented as follows.
#ControllerAdvice
public class LocalExceptionHandler {
#ExceptionHandler(PropertyReferenceException.class)
public ResponseEntity<Object> handlePropertyReferenceException(PropertyReferenceException ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
}
#ExceptionHandler(HttpMessageConversionException.class)
public ResponseEntity<Object> handleHttpMessageConversionException(HttpMessageConversionException ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
}
}
I'm using a Spock specification for implementing the test. The setup is as follows.
MockMvc mvc
public JsonSerializer[] buildJsonSerializers() {
return new JsonSerializer[]{new LocalDateSerializer(DateTimeFormatter.ofPattern(DATE_FORMAT)),
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT))};
}
Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
return builder -> {
builder.simpleDateFormat(DATE_TIME_FORMAT);
builder.serializers(buildJsonSerializers());
};
}
protected ObjectMapper buildObjectMapper() {
def objectMapperBuilder = new Jackson2ObjectMapperBuilder()
jsonCustomizer().customize(objectMapperBuilder)
objectMapperBuilder.modules(new MoneyModule()
.withMonetaryAmount(Money::of)
.withAmountFieldName("number")
.withFormattedFieldName("pretty"))
objectMapperBuilder.build()
}
def setup() {
ObjectMapper mapper = buildObjectMapper()
def mockMvcBuilder = MockMvcBuilders
.standaloneSetup(controller)
.setControllerAdvice(LocalExceptionHandler.class)
.setMessageConverters([new MappingJackson2HttpMessageConverter(mapper)]
.toArray(new HttpMessageConverter[1]))
.setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver())
mvc = mockMvcBuilder.build()
}
So the above setup just sets the date format through a customizer and then builds the object mapper using the Jackson2ObjectMapperBuilder.
The problem with that setup is that the builder is causing an object mapper configuration that results in a weird MockMvc behaviour.
When posting a bad request to a controller, a proper Exception is thrown and handled by one of the above exception handlers but request processing is not stopped and the controller method is invoked.
When running the production code (as Spring Boot application) error handling is just fine resulting with a HTTP 400.
Just by removing the builder and mimicking just the configuration desired for the test (which is a proper date time format) the test works as expected and request processing is stopped after exception handling.
So basically instead of using the builder I do
def mapper = new ObjectMapper()
mapper.registerModule(new MoneyModule()
.withMonetaryAmount(Money::of)
.withAmountFieldName("number")
.withFormattedFieldName("pretty"))
SimpleModule serializerModule = new SimpleModule()
Arrays.asList(buildJsonSerializers())
.forEach({ s -> serializerModule.addSerializer(s.handledType(), s) })
mapper.registerModule(serializerModule)
So it really looks like the builder is adding some configuration that MockMvc doesn't really deal with properly.
Would appreciate hints on resolving this.

How to start with PACT contract testing in java for a newbie

I have to do a POC on contract testing using pact, but I couldn't found anything helpful for a newbie. Can someone help me with the working code, how to install, execute I will be grateful.
I tried to explain below.
Consumer: Contract created by consumer.
Provider: Contracts tested by provider.
Pack Broker: After contracts are created under location (like targer/pacts) defined by you, you must publish the contracts to the common platform where consumer and provider will see.
Consumer side - Create contract for provider
public class CreateContractForProvider {
#Rule //Provider, HostInterface and Port defined with #Rule annotation (Used PactProviderRuleMk2)
public PactProviderRuleMk2 pactProviderRuleMk2 = new PactProviderRuleMk2(
// Provider Application Name
"ProviderName",
//Mock Server
"localhost",
8112,
this);
#Pact(consumer = "ConsumerName") // Consumer Application Name (Our application) - Consumer defined with #Pact annotation(
public RequestResponsePact createPact(PactDslWithProvider builder) {
Map<String, String> headers = new HashMap();
headers.put("Content-Type", "application/json"); //Defined headers
//Defined responses with PactDslJsonBody()
DslPart expectedResultBodyWhenGetPayments = new PactDslJsonBody()
.integerType("id",308545)
.integerType("contractNo",854452)
.numberType("amount",3312.5)
.stringType("status","UNPAID")
.asBody();
return builder
.uponReceiving("A request for all payments")
.path("/payments")
.method("GET")
.willRespondWith()
.status(200)
.headers(headers)
.body(expectedResultBodyWhenGetPayments).toPact(); //Response bodyies and headers used in return builder
// We can define more than one endpoint with .uponReceiving or .given
//Then we have to test beacuse contracts are created test stage.
//When we say test with #PactVerification, the server we described above stands up(localhost:8112). İf we get localhost:8112/(definedpathlike/payments) its return expectedResultBodyWhenGetPayments.If the test is successful, the contracts is create.
#Test
#PactVerification()
public void pactVerification() {
int contractNo=((Integer) new ContractTestUtil(pactProviderRuleMk2.getPort()).getContractResponse("/payments","contractNo")).intValue();
assertTrue(contractNo == 854452);
}}
Test Util
public class ContractTestUtil {
int port=8111;
public ContractTestUtil(int port) {
this.port=port;
System.out.println("Custom port "+port);
}
public Object getContractResponse(String path,String object) {
try {
System.setProperty("pact.rootDir", "./target/pacts");
System.setProperty("pact.rootDir", "./target/pacts");
String url=String.format("Http://localhost:%d"+path, port);
System.out.println("using url: "+url);
HttpResponse httpResponse = Request.Get(url).execute().returnResponse();
String json = EntityUtils.toString(httpResponse.getEntity());
System.out.println("json="+json);
JSONObject jsonObject = new JSONObject(json);
return jsonObject.get(object);
}
catch (Exception e) {
System.out.println("Unable to get object="+e);
return null;
}
}}
Define Pact Broker
The PactBrokerUr lmust be defined before publishing in pom.
<plugin>
<!-- mvn pact:publish -->
<groupId>au.com.dius</groupId>
<artifactId>pact-jvm-provider-maven_2.11</artifactId>
<version>3.5.10</version>
<configuration>
<pactDirectory>./target/pacts</pactDirectory> <!-- Defaults to ${project.build.directory}/pacts -->
<pactBrokerUrl>http://yourmachine:8113</pactBrokerUrl>
<projectVersion>1.1</projectVersion> <!-- Defaults to ${project.version} -->
<trimSnapshot>true</trimSnapshot> <!-- Defaults to false -->
</configuration>
</plugin>
Now, we can publish with pact:puplish command.
Provider Side - Call contracts created by consumer
In this stage you can test with failsafe plugin. Beacuse its integraion test.
#RunWith(PactRunner.class) // Say JUnit to run tests with custom Runner
#Provider("ProviderName")
#Consumer("ConsumerName")// Set up name of tested provider// Provider Application Name
#PactBroker(port = "8113", host = "yourmachine")
public class VerifyContractsWhichCreatedForProviderIT {
private static ConfigurableWebApplicationContext configurableWebApplicationContext;
#BeforeClass
public static void start() {
configurableWebApplicationContext = (ConfigurableWebApplicationContext)
SpringApplication.run(Application.class);
}
#TestTarget // Annotation denotes Target that will be used for tests
public final Target target = new HttpTarget(8080); //Test Target
}
Finally,you can create contrats and verify contrast created for you with clean test pact:publish verify command.

FakeMessageContext throws NullReferenceException

I'm trying to write unit test for my saga. I have used SagaFixture to host my Saga and using FakeBus. I have also used FakeMessageContext because, in a Saga exectution I'm using MessageContext to get return address.
Now, when I'm trying to call Handle method on Fixture, it throws exception of type NullReferenceException.
Pasting code below:
SearchSaga
public class SearchSaga : Saga<SearchSagaData>, IAmInitiatedBy<PersonRequested>, IHandleMessages<PersonSearchCompleted>
{
public void Handle(PersonRequested message)
{
Data.Id = new Guid(message.MessageId);
Data.ReturnAddress = MessageContext.GetCurrent().ReturnAddress;
Bus.Publish(message);
}
}
SagaUnitTest
[Test]
public void PublishResponseOfTypeSearchPersonRequest()
{
var bus = new FakeBus();
var saga = new SearchSaga(bus);
var fixture = new SagaFixture<SearchSagaData>(saga);
FakeMessageContext.Reset();
var fakeContext = MockRepository.GenerateMock<IMessageContext>();
fakeContext.Stub(s => s.ReturnAddress).Return("queuename");
fakeContext.Stub(s => s.Headers).Return(new Dictionary<string, object>());
// act
using (FakeMessageContext.Establish(fakeContext))
{
fixture.Handle(new PersonRequested {MessageId = Guid.NewGuid().ToString(), Query = "Abc"});
}
var sentRequests = bus.PublishedMessages.OfType<SearchPersonRequest>().ToList();
Assert.That(sentRequests.Count, Is.EqualTo(1));
}
Error Stacktrace:
at Rebus.SagaContext..ctor(Guid id)
at Rebus.Bus.Dispatcher.DispatchToHandler[TMessage](TMessage message, IHandleMessages1 handler) at Rebus.Testing.SagaFixture1.Handle[TMessage](TMessage message)
The exception is caused by the fact that your IMessageContext mock has a null value on the Items property. The thrown exception is just pretty bad, but I'll make sure that the reported error gets better in the future.
For now, you can fix the situation by setting up a an items dictionary like so:
fakeContext.Stub(s => s.Items).Return(new Dictionary<string, object>());
Moreover, instead of using MessageContext.GetCurrent() to get to the message context inside your handler, you should take advantage of the fact that all Rebus' IoC container adapters ensure that you can have an IMessageContext injected into all of your handler instances.
This way, there's no need to use FakeMessageContext in your unit tests.

Web API controller parameterized constructor called only once, parameterless constructor on subsequent requests

I'm attempting to use Unity to inject a dependency per this article:
http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver
Here is what I have in my global.asax
void ConfigureApi(HttpConfiguration config)
{
var unity = new UnityContainer();
unity.RegisterType<CustomerController>();
unity.RegisterType<TPS.Data.Can.IUnitOfWork, TPS.Data.Can.EFRepository.UnitOfWork>(new HierarchicalLifetimeManager());
config.DependencyResolver = new IoCContainer(unity);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ConfigureApi(GlobalConfiguration.Configuration);
}
Here is my API controller:
public class CustomerController : ApiController
{
private TPS.Data.Can.IRepository<tblCustomer> _repo;
private TPS.Data.Can.IUnitOfWork _uow;
public CustomerController() { }
public CustomerController(TPS.Data.Can.IUnitOfWork uow) {
_uow = uow;
_repo = uow.CustomerRepository;
}
// GET api/customer/5
public IEnumerable<Customer> Get()
{
string identity = HttpContext.Current.User.Identity.Name;
//REFACTOR THIS
if (String.IsNullOrWhiteSpace(identity))
identity = "chardie";
var customers = from c in _repo.Get()
where c.SalesRep == identity
select new Customer
{
IDCUST = null,
CustCode = c.CustCode,
CustName = c.CustName
};
return customers.ToList();
}
This works when I first start debugging my application. If I set a breakpoint in the parameterized constructor, the breakpoint will be hit when I hit the Web API for the first time. When I hit refresh in my browser, the constructor does not get called, the dependency doesn't get injected, and the Get() action throws an exception because the expected repository is null.
Can anyone tell me why my constructor isn't being called after the first request?
Thanks!
Chris
EDIT
FWIW, I removed the parameterless constructor entirely from the Web API controller, and on my second request to it, I get the exception:
Type 'TPS.Website.Api.CustomerController' does not have a default constructor
So it appears I'm getting my repo dependency injected on the first request, but after that every instantiation of the Web API controller is done through the parameterless constructor.
You're not specifying a lifecycle for the controller. MSDN states
If you do not specify a value for the lifetime, the instance will have
the default container-controlled lifetime. It will return a reference
to the original object on each call to Resolve.
If the IUnitOfWork dependency is transient, then the controller should be transient too. So try
unity.RegisterType<CustomerController>(new TransientLifetimeManager());
This might not solve the whole problem but it sounds like part of it. You certainly shouldn't need the parameterless constructor.
I had this as I was returning my resolver for my dependency scope using this and then disposing the container in the dispose. So after the first request the container was disposed.
Looks like it's because you're not using singleton pattern for the Unity Container.
Have a private static variable instead of the var container = new UnityContainer();
internal static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() => new UnityContainer());
Then access within code using the .Value property.

Resources