it-swarm.com.de

So senden Sie ein Mock-Objekt als JSON in mockmvc

Ich möchte ein Mock-Objekt im Controller über MockMvc mit dem Inhaltstyp JSON senden. Wenn ich versuche, den Mock zu serialisieren, lautet der Fehler:

Java.lang.UnsupportedOperationException: Expecting parameterized type, got interface org.mockito.internal.MockitoInvocationHandler.
 Are you missing the use of TypeToken idiom?

Mein Code lautet wie folgt: 

@Test
public void testSomething(){

    String xyz = "";
    Integer i = 10;
    SomeClass inst = mock(SomeClass.class, withSettings().serializable());
    when(inst.getProperty1()).then(xyz);
    when(inst.getProperty2()).then(i);

    Gson gson = new Gson();
    String json = gson.toJson(inst); // this is creating error

    this.mockmvc.perform(put("/someUrl/").contentType(MediaType.JSON).content(json)).andExpect(status().isOk());
}

Kann mir jemand sagen, was mir fehlt?

13
Sourabh

Ich schlage vor, dass Sie ein stub Ihrer SomeClass erstellen, das bekannte Werte für die getProperty1()- und getProperty2()-Methode zurückgibt. Abhängig von der Implementierung von SomeClass können Sie entweder direkt eine new-Instanz davon erstellen, eine Unterklasse überschreiben und einige Methoden überschreiben, eine anonyme innere Klasse erstellen, wenn es sich um eine Schnittstelle handelt, usw.

@Test
public void testSomething(){

    String xyz = "";
    Integer i = 10;

    // alt 1:
    SomeClass stub = new SomeClass(xyz, i);

    // alt 2: 
    SomeClass stub = new StubSomeClass(xyz, i); // StubSomeClass extends SomeClass

    // alt 3: 
    SomeClass stub = new SomeClass() {
         @Override
         String getProperty1() {
             return xyz;
         }
         @Override
         Integer getProperty2() {
             return i;
         }
    }

    Gson gson = new Gson();
    String json = gson.toJson(stub);

    this.mockmvc.perform(put("/someUrl/")
        .contentType(MediaType.APPLICATION_JSON).content(json))
        .andExpect(status().isOk());
}
23
matsev

Selbst wenn es möglich wäre, ein Mock-Objekt an einen JSON-Konverter zu senden, würde ein Einheitentest für diesen Vorgang angenommen: Das Mock-Objekt kann viele Attribute und Methoden aufweisen, die weit über die reale Klasse hinausgehen, und die Serialisierung kann zu einem wirklich komisch) führen Ergebnis.

IMHO, da es sich um einen Komponententest handelt, sollten Sie den seriellen Json-String von Hand schreiben. Sie können auch andere Tests durchführen, wenn Sie steuern möchten, wie Gson die Serialisierung durchführt

7
Serge Ballesta

Ich habe einen Weg gefunden, ein Mock-Objekt auf folgende Weise zu serialisieren:

Gson gson = new GSon();
String json = gson.toJson(mockedObject, mockedObjectType.class);

Obwohl ich einen USELESS-Fall versucht habe, da Json all die Spottarbeit, die ich in der test () - Funktion zur Verfügung gestellt habe, entfernt wird. Wenn das Objekt neu erstellt wird, hat es keinen Spottwert, und es wird zuerst NullPointerException ausgelöst Instanz der Verwendung einer Funktion/Eigenschaft.

BEARBEITEN: Wenn Sie Nullen serialisieren möchten, gibt es auch dafür eine Funktion:

Gson gson = new GsonBuilder().serializeNulls().create();
1
Sourabh

Wir hatten ein ähnliches Problem: Es gab eine Protokollierungsanweisung zum Ausgeben eines Objekts, das in json serialisiert wurde. Und ein Gerätetestfall für diesen Fehler ist aufgetreten, weil der Gson das Scheinobjekt nicht serialisieren konnte ..__ Es wurde mit einer Ausschlussstrategie gelöst, die die Serialisierungsklasse und Felder des Typs Klasse überspringt.

 private final Gson gson = new GsonBuilder()
     .setExclusionStrategies(new ExclusionStrategy() {
    @Override
    public boolean shouldSkipClass(Class<?> clazz) {
        return clazz instanceof Class;
    }

    @Override
    public boolean shouldSkipField(FieldAttributes field) {
        return field.getDeclaredClass() == Class.class;
    }
}).create();
1

In der Testkonfiguration können Sie den Standard-Nachrichtenkonverter mit einem anderen Nachrichtenkonverter, der die Serialisierung eines Objekts unterstützt, in String umschließen.

package com.example;

import org.Apache.commons.io.IOUtils;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;

import Java.io.IOException;
import Java.util.Arrays;

public class MockObjectHttpMessageConverter extends AbstractHttpMessageConverter {


  private final AbstractHttpMessageConverter primaryConverter;

  public MockObjectHttpMessageConverter(AbstractHttpMessageConverter primaryConverter) {
    this.primaryConverter = primaryConverter;
    setSupportedMediaTypes(Arrays.asList(MediaType.ALL));
  }

  @Override
  protected boolean supports(Class clazz) {
    return true;
  }

  @Override
  protected Object readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
    throw new UnsupportedOperationException();
  }

  @Override
  protected void writeInternal(Object o, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
    try {
      primaryConverter.write(o, MediaType.ALL, outputMessage);
    } catch (Exception e) {
      IOUtils.write(o.toString(), outputMessage.getBody());
    }
  }
}

In Spring's XML-Kontext:

<mvc:message-converters>
    <bean class="com.example.MockObjectHttpMessageConverter">
        <constructor-arg>
            <bean class="org.springframework.http.converter.json.GsonHttpMessageConverter">
                <property name="gson">
                    <bean class="com.google.gson.Gson" factory-bean="gsonBuilder" factory-method="create"/>
                </property>
            </bean>
        </constructor-arg>
    </bean>
</mvc:message-converters>
0
exe_sys