When I create a Service with ServiceStack and can them easily test when just instanciating the class and running my unit tests.
But with this approach the validators don't get fires, because the runtime binds them and they are triggert before the serivce is called.
Do I have to make IntegrationTests with a running service ? Or is there a smarter way`?
We do both: unit test the actual validator and then also full integration test - so we can test out the whole filter pipeline.
Our unit tests look some thing like:
[Test]
public void Validate_POST_ValidRequest_ExpectIsValidTrue()
{
var request = new MyRequest { Id =99, Name = "fr", Venue = "My Venue", Age = 9 };
var validateRunner = new MyValidator();
var result = validateRunner.Validate(request, ruleSet: "POST");
Assert.That(result.IsValid, Is.True);
}
It depends on what actually you want to test.
You can make a test just for your validator class passing different DTO Request objects.
You can also make an integration test by inheriting your test fixture from TestBase.
Related
How can I unit test this code?
private ODataQueryResult buildAndExecuteQuery(String path String entity,
String sapClient, String sapLanguage) {
ODataQuery query = ODataQueryBuilder
.withEntity(path, entity)
.withHeader("sap-client", sapClient, true)
.withHeader("sap-language", sapLanguage, true)
.withoutMetadata()
.build();
return query.execute();
}
More precisely: How can I verify that my code calls all the right functions, for example does not forget to call withoutMetadata or set the required headers?
Unfortunately, ODataQueryBuilder and ODataQuery are classes, not interfaces. which makes mocking tricky. ODataQueryBuilder is even final, disabling mocking completely. Also, the chain starts with a static method withEntity which can also not be mocked.
Are there helpers that allow me to spy on behavior or mock data, similar to the MockUtil described in https://blogs.sap.com/2017/09/19/step-12-with-sap-s4hana-cloud-sdk-automated-testing/?
You are right, the structure of those classes make them hard to mock, but as they are part of the "SAP Cloud Platform SDK for Service Development" we have no way to change them.
Other approaches might be:
If you want to stay with the Unit Test approach you might want to have a look at https://github.com/powermock/powermock. This would allow you to mock final and static classes and methods. However, I have never used it personally, so I'm not sure how easy/comfortable to use it is.
If you also would see an integration test suiting you could consider using http://wiremock.org/docs/getting-started/. With that you would be able to setup a "Mock Server", preparing responses for defined requests and with that verify the content of any HTTP call made by your test.
We use WireMock in the SAP Cloud SDK and also provide some integration into our SDK via the MockUtil contained in our testutil-core module.
I hope this helps a bit!
Partial solution is to simulate executing the ODataQuery on a mock HttpClient.
First, the original method needs to be taken apart into two independent parts, one for building the query, the other for executing it. This is good design anyway, so no big problem:
private ODataQuery buildQuery(String path, String entity,
String sapClient, String sapLanguage) {
return ODataQueryBuilder
.withEntity(path, entity)
.withHeader("sap-client", sapClient, true)
.withHeader("sap-language", sapLanguage, true)
.withoutMetadata()
.build();
}
private ODataResponse executeQuery(ODataQuery query) {
return query.execute();
}
The buildQuery method can now be tested as follows:
#Test
public void addsSapLanguageToHeader() throws ODataException, IOException {
ODataQuery query = cut.buildQuery("api/v2", "business-partners", "", "fr");
HttpUriRequest request = getRequest(query);
assertContainsHeader(request, "sap-language", "fr");
}
The method getRequest produces a fake HttpClient that stubs all methods required to get query.execute(httpClient) to work. It stores the actual request and returns it for further inspection. Sample implementation with Mockito:
private HttpUriRequest getRequest(ODataQuery query) throws ODataException, IOException {
// stub methods to make code work
HttpResponse response = mock(HttpResponse.class);
when(httpClient.execute(any())).thenReturn(response);
StatusLine statusLine = mock(StatusLine.class);
when(response.getStatusLine()).thenReturn(statusLine);
HttpEntity entity = mock(HttpEntity.class);
when(response.getEntity()).thenReturn(entity);
InputStream inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
when(entity.getContent()).thenReturn(inputStream);
Header[] headers = new Header[0];
when(response.getAllHeaders()).thenReturn(headers);
// simulate the execution of the query
query.execute(httpClient);
// grab the original argument from the mock for inspection
ArgumentCaptor<HttpUriRequest> captor = ArgumentCaptor.forClass(HttpUriRequest.class);
verify(httpClient).execute(captor.capture());
HttpUriRequest request = captor.getValue();
return request;
}
This solution is far from perfect, of course.
First, the amount of code needed to make this work alone shows how fragile this test will be over time. Whenever the CloudSDK decides to add a method or validation to the call sequence, this test will break. Note also that the test is invasive, by testing a private method, while gold standards say we should test only public methods.
Second, the method executeQuery can still not be tested. Execution paths also differ, because the test code uses the .execute(httpClient) variant to run the query, while the original code uses the .execute(destinationName) variant. The two happen to share code, but this may change over time.
I want to write the testcase for the given method. But there exist a static Transport.sendEmail method.
How can I mock this method using MockitoJunitRunner.
public void sendEmail(final String message, final String contentType) {
final Session session = Session.getDefaultInstance(PROPERTIES, null);
final Multipart mpart = new MimeMultipart();
final MimeBodyPart body = new MimeBodyPart();
try {
body.setContent(message, contentType);
mpart.addBodyPart(body);
Transport.send(createMessage(session, mpart));
LOGGER.info("Email Notification Sent Successfully");
} catch (MessagingException | UnsupportedEncodingException e) {
LOGGER.error("Was not able to send mail", e);
}
So:
Transport.send(createMessage(session, mpart));
that static call means: you can't "control" it using Mockito. Plain and simple. If that call just "passes" in your unit test environment, well, then you can test it, but not verify that the call really took place. Worse, if that call throws some exception in the unit test setup, then heck, what could you do?
Options:
turn to PowerMock(ito) or JMockit, as they allow you to gain control
recommended: improve your design to be easy-to-test
That last idea comes in various flavors:
For example, you could create a minimal interface EmailSenderService that offers a void send(Message whatever) method. Next: you create one implementation of that interface that simply invokes that static method. Now your code that actually has to send that message ... simply gets passed in an instance of EmailSenderService. And within your unit tests, you can now #Mock that interface, and you gain control over it.
Alternatively, you simply deprecate that static method (maybe the whole class), and you design a new "real" EmailSenderService that doesn't rely on static methods.
The project is written using Play framework and Scala language.
I have implemented compile time dependency.
I have followed this example from Play:
https://github.com/playframework/play-scala-compile-di-example
Looking at the MyApplicationLoader.scala:
import play.api._
import play.api.routing.Router
class MyApplicationLoader extends ApplicationLoader {
private var components: MyComponents = _
def load(context: ApplicationLoader.Context): Application = {
components = new MyComponents(context)
components.application
}
}
class MyComponents(context: ApplicationLoader.Context)
extends BuiltInComponentsFromContext(context)
with play.filters.HttpFiltersComponents
with _root_.controllers.AssetsComponents {
lazy val homeController = new _root_.controllers.HomeController(controllerComponents)
lazy val router: Router = new _root_.router.Routes(httpErrorHandler, homeController, assets)
}
and the following line of code:
lazy val homeController = new _root_.controllers.HomeController(controllerComponents)
my understanding is that there is only one instance of HomeController created the first time HomeController is called.
And that instance lives as long as the application lives. Are these statements correct?
The HomeController in my application looks like that:
class HomeController{
val request = // some code here
val workflowExecutionResult = Workflow.execute(request)
}
So Workflow is of type object and not class.
The Workflow looks like that:
object Workflow {
def execute(request: Request) = {
val retrieveCustomersResult = RetrieveCustomers.retrieve()
// some code here
val createRequestResult = CreateRequest.create(request)
// some code here
workflowExecutionResult
}
}
So Workflow calls a few domain services and each domain service is of type object and not class.
All values inside the domain services are immutable, I am using vals everywhere.
Is this enough to ensure thread safety?
I am asking as I'm used to writing C# Web APIs where a HomeController would look like that:
class HomeControllerInSeeSharpProject{
// some code here
var request = new Request() // more code here
var workflow = new WorkflowInSeeSharpProject()
var workflowExecutionResult = workflow.execute(request)
}
and a Workflow would look like that:
public class WorkflowInSeeSharpProject {
public execute(Request request) {
var retrieveCustomers = new RetrieveCustomers()
var retrieveCustomersResult = retrieveCustomers.retrieve()
// some code here
var createRequest = new CreateRequest()
var createRequestResult = createRequest.create(request)
// some code here
return workflowExecutionResult
}
}
So in a C# project every time a HomeControllerInSeeSharpProject is called a new instance of WorkflowInSeeSharpProject is created and all the domain services
are also newed-up and then I can be sure that state cannot be shared between separate threads. So I am afraid that because my Scala Workflow
and domain services are of type object and not class that there could be a situation where two requests are sent into the HomeController
and state is shared between those two threads.
Can this be the case? Is my application not thread safe?
I have read that objects in Scala are not thread safe since there is only single instance of them. However I have also read that although
they are not thread safe using vals will make the application thread safe...
Or maybe Play itself has a way to deal with that problem?
Because your are using compile time dependency injection, you control the number of instances created, and in your case HomeController is created only once. As requests come in, this single instance will be shared between threads so indeed you have to make sure it is thread-safe. All the dependencies of HomeController will also need to be thread-safe, thus object Workflow has to be thread-safe. Currently, Workflow is not publicly exposing any shared state, so it is thread-safe. In general, val definitions within object are thread-safe.
In effect HomeController is behaving like a singleton and avoiding singletons could be safer. For example, by default Play Framework uses Guice dependency injection which creates a new controller instance per request as long as it is not a #Singleton. One motivation is there is less state to worry about regarding concurrency protection as suggested by Nio's answer:
In general, it is probably best to not use #Singleton unless you have
a fair understanding of immutability and thread-safety. If you think
you have a use case for Singleton though just make sure you are
protecting any shared state.
My problem is...
...I have a DTO like this
[Route("/route/to/dto/{Id}", "GET")]
public class Foo : IReturn<Bar>
{
public string Id { get; set; }
}
and need to call the service that implements the method with this signature
public Bar Get(Foo)
from a request and/or response filter. I don't know what class implements it (don't want to need to know). What I need is something like the LocalServiceClient class in the example below:
var client = new LocalServiceClient();
Bar bar = client.Get(new Foo());
Does this LocalServiceClient thing exists? JsonServiceClient has a pretty similar interface, but using it would be inneficient (I need to call my own service, I shouldn't need an extra round-trip, even to localhost, just to do this).
I'm aware of ResolveService method from Service class, but it requires me to have a service instance and to know what class will handle the request.
I think this LocalServiceClient is possible because I have all the data that a remote client (e.g. JsonServiceClient) needs to call the service - request DTO, route, verb - but couldn't find how to do it. Actually, it should be easier to implement than JsonServiceClient.
JsonServiceClient would do it, but there must be a better way, using the same request context.
What I want to do (skip this if you're not curious about why I'm doing this)
Actually, my DTOs are like this:
[EmbedRequestedLinks]
[Route("/route/to/dto/{Id}", "GET")]
public class MyResponseDto
{
public string Id { get; set; }
public EmbeddableLink<AResponseDto> RelatedResource { get; set; }
public EmbeddableLink<AnotherResponteDto> AnotherRelatedResource { get; set; }
}
EmbedRequestedLinksAttribute is a request/response filter. This filter checks if there is a query argument named "embed" in the request. If so, the filter need to "embed" the comma-separated related resources referenced by the argument into the response to this request. EmbeddableLink<T> instances can be obtained by using extension methods like these:
1) public static EmbeddableLink<T> ToEmbeddableLink<T>(this IReturn<T> requestDto)
2) public static EmbeddableLink<T> ToEmbeddableLink<T>(this T resource)
Assume a client places this request:
GET /route/to/dto/123456?embed=relatedResource HTTP/1.1
The service that will handle this request will return an instance of MyResponseDto with EmbeddableLinks created using signature (1). Then my response filter will see the embed query argument and will call the Get method of the appropriate service, replacing the RelatedResource with another instance of EmbeddableLink, this time created using extension method (2):
var client = new LocalServiceClient();
response.RelatedResource = client.Get(response.RelatedResource.RequestDto)
.ToEmbeddableLink();
The serialization routine of EmbeddableLink takes care of the rest.
In case an embeddable link is not included in the embed list the serialization routine will call the extension method ToUrl (provided by ServiceStack), that takes a verb and converts a request DTO into a URL. In this example the client will get this response:
{
"id": "9asc09dcd80a98",
"relatedResource": { "id": "ioijo0909801", ... },
"anotherRelatedResource":
{
"$link": { "href": "/route/to/another/dto/1sdf89879s" }
}
}
I know the creators of ServiceStack think that polymorphic request/responses are bad things but this case seems OK to me because I'm not creating services, instead I'm extending the framework to help me create services the way I (and possibly other users of ServiceStack) need. I'm also creating other hypermedia extensions to ServiceStack. (I hope my boss allow me to publish these extensions on github)
If you really want to do this then look the source code for ServiceStack. Look at the ServiceManager and ServiceController. These classes are responsible for registering and resolving services. You might even be able to use reflection to create services on the fly with the static EndpointHost.Metadata like so:
var operation = EndpointHost.Metadata.Operations
.FirstOrDefault(x => x.RequestType == typeof(Person));
if (operation != null)
{
var svc = Activator.CreateInstance(operation.ServiceType);
var method = operation.ServiceType.GetMethod("Get");
var response = method.Invoke(svc, new[] { new Person() });
}
This kinda works but you will get NULL exceptions if there is other code calling
var httpRequest = RequestContext.Get<IHttpRequest>();
But I would not suggest this.
Instead if you create your own Business Service classes that do all the CRUD operations (POST/PUT/GET ect). Then make the ServiceStack Services thin wrappers over them. Now you can call your own services whenever you want without worrying about the HTTP Request and ServiceStack. Only use the ServiceStack Service when you are dealing with HTTP requests
You can call the static AppHostBase.Resolve() method as demonstrated here, calling a SeviceStack Service from an MVC controller:
var helloService = AppHostBase.Resolve<HelloService>();
helloService.RequestContext = System.Web.HttpContext.Current.ToRequestContext();
var response = (HelloResponse)helloService.Any(new HelloRequest { Name = User.Identity.Name });
However, I would take #kampsj's approach of making your ServiceStack services a thin wrapper around your application service classes and only deal with HTTP/Session specific stuff in the ServiceStack service.
Can i start by saying i am new to programming and SoapUI(more like a week old). i apologies in advance for asking the question(s) i am about to ask.
Problem
basically, i am trying to automate webservice.
I need to create xml using Groovy in soapui and send it as part of a request body to a webservice(REST not SOAP) and do some assertion on the response received. i will be sending quite a few request, hence the reason to automate.
My proposed solution (which i am not sure about)
import groovyx.net.http.HTTPBuilder
import groovyx.net.http.ContentType
import groovyx.net.http.Method
class XmlGenerator {
// I created a class i.e. called XmlGenerator with a
// static method called GetXML() which looks like this:
public static def GetXML()
{
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.GetDMessage() //creating the xml message
{
PrescribedItems
{
PrescribedMethod(xml,'Some Value','Some Value','Some Value')
PrescribedItem
{
PrescribedMethod(xml,'Some Value','Some Value','Some Value')
}
}
}
return writer
}
// This method creates the XML needed but then i need to
// pass the xml generated to a request boy; so i
//create another method within the same class:
static def postXML(String baseUrl, String path)
{
def RequestBody = XmlGenerator.GetXML() // i am not sure if this will work
try
{
def ret = null
def http = new HTTPBuilder(baseUrl)
http.request(Method.POST, ContentType.XML)
{
uri.path = path
body = RequestBody
}
}
catch (groovyx.net.http.HttpResponseException ex)
{
ex.printStackTrace()
return null
}
catch (java.net.ConnectException ex)
{
ex.printStackTrace()
return null
}
}
}
Summary
A class called XmlGenerator() with 2 methods; GetXML() (used to generate XML ) and postXML() (Used to send XML generated by GetXML() to the Webservice.)
Questions
How can i make sure that this 2 methods ( GetXML() and postXML() ) are used by other request messages i.e. do i need to import the groovy scripte.g. do i do an import ... GroovyScriptName , if yes, please how?
How can i create create the xml and run the request in subsequent request messages. For instance;
do i do this; XmlGenerator() gen = new XmlGenerator(), then do gen.GetXML() and gen.postXML() to create and run the request. Also, what role can testRunner play in all this
Running the code currently throws up HTTPBuilder, ContentType , Method can not be resolved even though i have imported them in the script (see above)
Finally, what role can property play in building this framework? bearing in mind that the each request will be independent from the other request i.e. nothing is been passed around from one request to the other during test execution
You can specify the REST request you are testing using standard soapui functionality, as outlined here:
http://www.soapui.org/REST-Testing/getting-started.html
Follow the steps in the above page to create a:
New REST Service
New REST Resource
New REST Method
Then you can add a REST Test Step to your Test Case that invokes that request.
You can then insert a Groovy Test Step before the REST Test Step to build your xml body; here's a simple example of building a XML string:
import groovy.xml.MarkupBuilder
context.writer = new StringWriter()
def xml = new MarkupBuilder(context.writer)
xml.books() {
book(name:'blue ocean') {
format ('paperback')
year ('2010')
}
book(name:'quicksilver') {
format ('hardback')
year ('2011')
}
}
Note that the XML is assigned to a context variable (context.writer). This makes it available for use in subsequent steps within the scope of the Test Case for the duration of the test run.
Then, insert the following code into the body of your REST Test Step:
${=context.writer}
Finally, you have the option of adding Assertions within the REST Test Step; here's some information on that:
http://www.soapui.org/Functional-Testing/getting-started-with-assertions.html