GVKun编程网logo

如何干净地测试使用DomainClassConverter检索参数的Spring控制器?(springerlink检索式)

16

针对如何干净地测试使用DomainClassConverter检索参数的Spring控制器?和springerlink检索式这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展c#–如何使用In

针对如何干净地测试使用DomainClassConverter检索参数的Spring控制器?springerlink检索式这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展c# – 如何使用InvariantCulture调用TypeConverter.ConvertTo或ConvertToString但不实现ITypeDescriptorContext、cannot convert from pointer to base class ''QObject'' to pointer to derived class ''subC...、com.beust.jcommander.converters.IntegerConverter的实例源码、com.intellij.util.xml.converters.values.ClassArrayConverter的实例源码等相关知识,希望可以帮助到你。

本文目录一览:

如何干净地测试使用DomainClassConverter检索参数的Spring控制器?(springerlink检索式)

如何干净地测试使用DomainClassConverter检索参数的Spring控制器?(springerlink检索式)

我擅长进行干净,隔离良好的单元测试。但是我在这里的“干净”部分碰巧测试一个控制器,该控制器使用DomainClassConverter功能获取实体作为其映射方法的参数。

@Entityclass MyEntity {    @Id    private Integer id;    // rest of properties goes here.}

像这样定义控制器

@RequestMapping("/api/v1/myentities")class MyEntitiesController {    @Autowired    private DoSomethingService aService;    @PostMapping("/{id}")    public ResponseEntity<MyEntity> update(@PathVariable("id")Optional<MyEntity> myEntity) {        // do what is needed here    }}

因此,从DomainClassConverter小型文档中,我知道它用于CrudRepository#findById查找实体。我想知道的是如何在测试中清晰地进行模拟。通过执行以下步骤,我取得了一些成功:

  1. 创建一个我可以模拟的自定义转换器/格式化程序
  2. 使用上述转换器实例化我自己的MockMvc
  3. 重置模拟并在每次测试时更改行为。

问题在于设置代码很复杂,因此难以调试和解释(我的团队是来自Rails或uni的99%的初级人员,因此我们必须保持简单)。我想知道是否有一种方法可以MyEntity在继续使用进行测试的同时从单元测试中注入所需的实例@Autowired
MockMvc

目前,我正在尝试查看是否可以插入CrudRepositoryfor 的模拟物,MyEntity但没有成功。几年来我一直没有在Spring /
Java中工作(4),所以我对可用工具的了解可能不是最新的。

答案1

小编典典

因此,从DomainClassConverter小型文档中,我知道它使用CrudRepository#findById查找实体。我想知道的是如何在测试中清晰地进行模拟。

您将需要模拟2个在之前调用的方法,CrudRepository#findById以便返回所需的实体。下面的示例使用RestAssuredMockMvc,但是如果同时注入MockMvc,则可以执行相同的操作WebApplicationContext

@RunWith(SpringRunner.class)@SpringBootTest(classes = SomeApplication.class)public class SomeControllerTest {    @Autowired    private WebApplicationContext context;    @MockBean(name = "mvcConversionService")    private WebConversionService webConversionService;    @Before    public void setup() {        RestAssuredMockMvc.webAppContextSetup(context);        SomeEntity someEntity = new SomeEntity();        when(webConversionService.canConvert(any(TypeDescriptor.class), any(TypeDescriptor.class)))                .thenReturn(true);        when(webConversionService.convert(eq("1"), any(TypeDescriptor.class), any(TypeDescriptor.class)))                .thenReturn(someEntity);    }}

在某个时候,Spring
Boot将执行WebConversionService::convert,稍后将调用DomainClassConverter::convert,然后执行类似的操作invoker.invokeFindById,该操作将使用实体存储库查找实体。

那么为什么要嘲笑WebConversionService而不是DomainClassConverter呢?因为DomainClassConverter是在应用程序启动期间实例化的,没有注入:

DomainClassConverter<FormattingConversionService> converter =        new DomainClassConverter<>(conversionService);

同时,WebConversionService是一个可以让我们模拟它的bean:

@Bean@Overridepublic FormattingConversionService mvcConversionService() {    WebConversionService conversionService = new WebConversionService(this.mvcProperties.getDateFormat());    addFormatters(conversionService);    return conversionService;}

将模拟bean命名为mvcConversionService,这一点很重要,否则它将不会替换原始bean。

关于存根,您将需要模拟2个方法。首先,您必须告诉您的模拟可以转换任何内容:

when(webConversionService.canConvert(any(TypeDescriptor.class), any(TypeDescriptor.class)))        .thenReturn(true);

然后是main方法,它将与URL路径中定义的所需实体ID相匹配:

when(webConversionService.convert(eq("1"), any(TypeDescriptor.class), any(TypeDescriptor.class)))        .thenReturn(someEntity);

到目前为止,一切都很好。但是匹配目标类型也不会更好吗?像eq(TypeDescriptor.valueOf(SomeEntity.class))什么?可以,但是这会创建TypeDescriptor的新实例,当在域转换期间调用此存根时,它将不匹配。

这是我使用过的最干净的解决方案,但是我知道,如果Spring允许,它可能会更好。

c# – 如何使用InvariantCulture调用TypeConverter.ConvertTo或ConvertToString但不实现ITypeDescriptorContext

c# – 如何使用InvariantCulture调用TypeConverter.ConvertTo或ConvertToString但不实现ITypeDescriptorContext

在我的转换方法中,当我使用TypeConverter.ConvertToString(Object)时,我得到了错误的数字分隔符,因为我的系统是德语.此方法还有另一个重载,如下所示:TypeConverter.ConvertToString(ITypeDescriptorContext,CultureInfo,Object).

除了在之前和之后切换文化之外,有没有一种聪明的方法来获取ITypeDescriptorContext或使用InvariantCulture调用此方法的其他选项?

解决方法

您可以将null作为参数传递
TypeConverter.ConvertToString(null,CultureInfo.InvariantCulture,Object);

cannot convert from pointer to base class ''QObject'' to pointer to derived class ''subC...

cannot convert from pointer to base class ''QObject'' to pointer to derived class ''subC...

QT 编译不过的另一个问题:

1. 新建一个console工程

QT -= gui

CONFIG += c++11 console
CONFIG -= app_bundle

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        main.cpp \
    baseclass.cpp \
    subclass.cpp \
    subclass2.cpp
    #grandclass.cpp

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

HEADERS += \
    baseclass.h \
    subclass.h \
    subclass2.h
    #grandclass.h

2. 添加baseClass

baseclass.h

#ifndef BASECLASS_H
#define BASECLASS_H

#include "QObject"

class baseClass: public QObject
{
    Q_OBJECT

public:
    baseClass(QObject * p = 0);
    virtual ~baseClass() {}

    virtual void vMethod(int) = 0;

signals:
    void signal1();


};

#endif // BASECLASS_H

baseclass.cpp

#include "baseclass.h"

baseClass::baseClass(QObject * p) : QObject(p)
{

}

3. 添加subClass

subclass.h

#ifndef SUBCLASS_H
#define SUBCLASS_H

#include "baseclass.h"

class subClass: virtual public baseClass
{
    Q_OBJECT

public:
    subClass(QObject * p = 0);
    virtual ~subClass() {};
    virtual void vMethod(int) = 0;

signals:
    void signal2();

};

#endif // SUBCLASS_H

subclass.cpp

#include "subclass.h"

subClass::subClass(QObject * p) : baseClass (p)
{

}

4. 添加subClass2

subclass2.h

#ifndef SUBCLASS2_H
#define SUBCLASS2_H

#include "baseclass.h"

class subClass2 : virtual public baseClass
{
    Q_OBJECT

public:
    subClass2(QObject * p = 0);

    virtual void vMethod(int) = 0;

};

#endif // SUBCLASS2_H

subclass2.cpp

#include "subclass2.h"

subClass2::subClass2(QObject * p) : baseClass (p)
{

}

5 main.cpp

#include <QCoreApplication>
#include "subclass.h"
//#include "grandclass.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);


    //grandClass * sub = new grandClass();

    return a.exec();
}

 

编译报错:/build-testQtSignalBug-Qt5_9_4_zynq-Debug/moc_subclass.cpp:68: error: cannot convert from pointer to base class ''QObject'' to pointer to derived class ''subClass'' via virtual base ''baseClass''

subClass *_t = static_cast<subClass *>(_o);
^

 

 

解决方法: 将subclass里的signals 删掉, 即不在subclass里声明信号量。

原因:不详。

 

com.beust.jcommander.converters.IntegerConverter的实例源码

com.beust.jcommander.converters.IntegerConverter的实例源码

项目:jcommander-addons    文件:AbstractBaseConverter.java   
/**
 * Converts the given value to an int for the given option.
 * 
 * @param optionName
 *            the option name
 * @param value
 *            the value to parse
 * @return the int result
 */
protected int toInt(final String optionName,final String value) {
    return new IntegerConverter(optionName).convert(value).intValue();
}

com.intellij.util.xml.converters.values.ClassArrayConverter的实例源码

com.intellij.util.xml.converters.values.ClassArrayConverter的实例源码

项目:intellij-ce-playground    文件:JavaDomApplicationComponent.java   
public JavaDomApplicationComponent(ConverterManager converterManager) {
  converterManager.addConverter(PsiClass.class,new PsiClassConverter());
  converterManager.addConverter(PsiType.class,new CanonicalPsiTypeConverterImpl());
  converterManager.registerConverterImplementation(JvmPsiTypeConverter.class,new JvmPsiTypeConverterImpl());
  converterManager.registerConverterImplementation(CanonicalPsiTypeConverter.class,new CanonicalPsiTypeConverterImpl());

  final ClassValueConverter classValueConverter = ClassValueConverter.getClassValueConverter();
  converterManager.registerConverterImplementation(ClassValueConverter.class,classValueConverter);
  final ClassArrayConverter classArrayConverter = ClassArrayConverter.getClassArrayConverter();
  converterManager.registerConverterImplementation(ClassArrayConverter.class,classArrayConverter);

}
项目:tools-idea    文件:JavaDomApplicationComponent.java   
public JavaDomApplicationComponent(ConverterManager converterManager) {
  converterManager.addConverter(PsiClass.class,classArrayConverter);

}
项目:consulo-java    文件:JavaDomApplicationComponent.java   
public JavaDomApplicationComponent(ConverterManager converterManager) {
  converterManager.addConverter(PsiClass.class,classArrayConverter);

}

关于如何干净地测试使用DomainClassConverter检索参数的Spring控制器?springerlink检索式的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于c# – 如何使用InvariantCulture调用TypeConverter.ConvertTo或ConvertToString但不实现ITypeDescriptorContext、cannot convert from pointer to base class ''QObject'' to pointer to derived class ''subC...、com.beust.jcommander.converters.IntegerConverter的实例源码、com.intellij.util.xml.converters.values.ClassArrayConverter的实例源码的相关知识,请在本站寻找。

本文标签: