您认为在项目中组织JUnit测试的最佳实践是什么?为什么?例如,您是否将测试放在他们测试的类旁边?你把它们放在一个单独但平行的包装结构中吗?您是否完全使用不同的组织策略?
编辑:更新以回应Ani B.
编辑2:添加了更新的PluginSecurityManager.
我的应用程序有一个插件机制,第三方可以提供包含实现特定接口的类的JAR.使用URLClassLoader,我能够加载该类并实例化它,没问题.因为代码可能不受信任,我需要防止它行为不端.例如,我在一个单独的线程中运行插件代码,这样如果它进入无限循环或者只是花费太长时间我就可以杀死它.但是尝试为他们设置一个安全沙箱,以便他们无法做出像网络连接或访问硬盘驱动器上的文件这样的事情让我感到非常沮丧.我的努力总是导致对插件没有影响(它具有与应用程序相同的权限)或者也限制了应用程序.我希望主应用程序代码能够完成它想要的任何东西,
关于这一主题的文献和在线资源是复杂,混乱和矛盾的.我已经阅读过各种各样的地方(例如这个问题),我需要提供一个自定义的SecurityManager,但是当我尝试它时,我遇到了问题,因为JVM延迟加载JAR中的类.所以我可以很好地实例化它,但是如果我在加载的对象上调用一个方法来实例化来自同一个JAR的另一个类,那么它就会爆炸,因为它被拒绝了从JAR读取的权利.
从理论上讲,我可以在SecurityManager中检查FilePermission,看看它是否正在尝试加载自己的JAR.这没关系,但URLClassLoader文档说:"默认情况下,加载的类只被授予访问创建URLClassLoader时指定的URL的权限." 那为什么我甚至需要一个自定义的SecurityManager?URLClassLoader不应该只处理这个吗?为什么不呢?
这是一个重现问题的简化示例:
package test.app;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import test.api.Plugin;
public class PluginTest {
public static void pluginTest(String pathToJar) {
try {
File file = new File(pathToJar);
URL url = file.toURI().toURL();
URLClassLoader cl = new URLClassLoader(new java.net.URL[] { url });
Class<?> clazz = cl.loadClass("test.plugin.MyPlugin");
final Plugin plugin = (Plugin) clazz.newInstance();
PluginThread thread = new PluginThread(new Runnable() {
@Override
public void run() {
plugin.go();
}
}); …
Run Code Online (Sandbox Code Playgroud) 我正在写一个GreaseMonkey脚本,我正在迭代一堆元素.对于每个元素,我需要一个字符串ID,以后我可以用它来引用该元素.元素本身没有id
属性,我不能修改原始文档给它一个(虽然我可以在我的脚本中进行DOM更改).我无法在我的脚本中存储引用,因为当我需要它们时,GreaseMonkey脚本本身将超出范围.例如,有没有办法获得浏览器使用的"内部"ID?只有Firefox的解决方案很好; 可以在其他场景中应用的跨浏览器解决方案非常棒.
编辑:
如果GreaseMonkey脚本超出范围,您以后如何引用这些元素?他们GreaseMonkey脚本正在向DOM对象添加事件.我无法将引用存储在数组或其他类似的机制中,因为当事件触发时,数组将会消失,因为GreaseMonkey脚本将超出范围.因此,事件需要某种方式来了解脚本在附加事件时所具有的元素引用.并且所讨论的元素不是它所附着的元素.
你不能只在元素上使用自定义属性吗?是的,但问题在于查找.我不得不求助于遍历所有元素,寻找将自定义属性设置为所需id的元素.那肯定会有用,但在大型文档中它可能非常耗时.我正在寻找浏览器可以执行查找工作的东西.
等等,你能否或不能修改文件?我无法修改源文档,但我可以在脚本中进行DOM更改.我会在问题中澄清一下.
你能不能使用封口?尽管我最初认为他们不会这样做,但Closuses确实有效.见我后来的帖子.
这听起来像是问题的答案:"我可以使用一些内部浏览器ID吗?" 没有."
我有一个传单地图,用于位置共享.当用户共享其位置时,会在地图中添加显示其位置的标记,供所有其他用户查看.无论何时添加,移动或删除一个标记,它都会自动调整地图以显示所有标记.我还添加了一个自定义控件,可以打开和关闭自动调整行为.这一切都很好,但我还想使地图足够智能,以便在用户平移或缩放地图时自动关闭自动调整行为.
事实证明这非常困难,因为我无法找到一种好方法来区分用户是启动平移/缩放操作还是自动调整.我最初是在听panstart和zoomstart事件,但这些事件也是由自动调整触发的.我想我可以设置一个标志,告诉它在自动调整引起缩放/平移时不要关闭自动调整.我在关闭自动调整以响应panstart和zoomstart之前先检查此标志,然后在收到panend和zoomend时将其清除.
这似乎工作正常,直到发生自动调整,不会导致平移或缩放.假设我们有一个大的自动拟合标记簇,并且中间的一个标记被移除.由于绑定框未更改,因此不会触发平移或缩放,因此不会清除告知其不关闭自动调整的标记.下次用户平移或缩放地图时,它不会像应该的那样关闭自动调整,因为它认为它仍处于自动调整操作的中间.
如何在用户直接平移或缩放地图时可靠地关闭自动调整,但在通过其他方式平移或缩放时将其保持打开状态?
这是相关代码:
var markers = []; // Map markers are stored in this array.
var autoFit = true; // Whether auto-fit is turned on
var lockAutoFit = false; // Temporarily lock auto-fit if true
var map; // Leaflet map object
function initMap() {
// Leaflet map initialized here
map.on('movestart zoomstart', function() {
if (!lockAutoFit) {
autoFit = false;
}
});
map.on('moveend zoomend', function() {
lockAutoFit = false;
});
}
function toggleAutoFit() {
autoFit = !autoFit;
if (autoFit) …
Run Code Online (Sandbox Code Playgroud) 我已经打了两天内部Eclipse错误了.我正在运行Eclipse的最新Spring Tool Suite版本,并且我试图导入一系列现有的Maven项目.每当我这样做时,Eclipse会抛出NullPointerException,但错误日志视图中没有可用的堆栈跟踪.如果我指示Eclipse更新Maven项目(Maven> Update Project),我会再次获得NullPointerException.这次,错误日志视图报告以下堆栈跟踪:
java.lang.NullPointerException
at org.eclipse.wst.common.componentcore.internal.resources.VirtualResource.getProjectRelativePaths(VirtualResource.java:119)
at org.eclipse.wst.common.componentcore.internal.resources.VirtualFile.getUnderlyingFiles(VirtualFile.java:104)
at org.eclipse.wst.common.componentcore.internal.resources.VirtualFile.getUnderlyingResources(VirtualFile.java:93)
at org.eclipse.wst.common.componentcore.internal.resources.VirtualResource.exists(VirtualResource.java:88)
at org.eclipse.jst.common.internal.modulecore.util.ManifestUtilities.getNonBinaryComponentManifest(ManifestUtilities.java:124)
at org.eclipse.jst.common.internal.modulecore.util.ManifestUtilities.getManifest(ManifestUtilities.java:81)
at org.eclipse.jst.common.internal.modulecore.util.ManifestUtilities.getManifestClasspath(ManifestUtilities.java:147)
at org.eclipse.jst.j2ee.componentcore.J2EEModuleVirtualComponent.getManifestClasspath(J2EEModuleVirtualComponent.java:248)
at org.eclipse.jst.j2ee.componentcore.J2EEModuleVirtualComponent.calculateManifestReferences(J2EEModuleVirtualComponent.java:368)
at org.eclipse.jst.j2ee.componentcore.J2EEModuleVirtualComponent.cacheManifestReferences(J2EEModuleVirtualComponent.java:360)
at org.eclipse.jst.j2ee.componentcore.J2EEModuleVirtualComponent.getReferences(J2EEModuleVirtualComponent.java:176)
at org.eclipse.jst.j2ee.componentcore.J2EEModuleVirtualComponent.getReferences(J2EEModuleVirtualComponent.java:214)
at org.eclipse.jst.j2ee.componentcore.J2EEModuleVirtualComponent.getReferences(J2EEModuleVirtualComponent.java:207)
at org.eclipse.m2e.wtp.WebProjectConfiguratorDelegate.configureClasspath(WebProjectConfiguratorDelegate.java:386)
at org.eclipse.m2e.wtp.WTPProjectConfigurator.configureClasspath(WTPProjectConfigurator.java:107)
at org.eclipse.m2e.jdt.internal.DefaultClasspathManagerDelegate.populateClasspath(DefaultClasspathManagerDelegate.java:61)
at org.eclipse.m2e.jdt.internal.BuildPathManager.getClasspath(BuildPathManager.java:253)
at org.eclipse.m2e.jdt.internal.BuildPathManager.getClasspath(BuildPathManager.java:363)
at org.eclipse.m2e.jdt.internal.BuildPathManager.getClasspath(BuildPathManager.java:343)
at org.eclipse.m2e.jdt.internal.BuildPathManager.getClasspath(BuildPathManager.java:371)
at org.eclipse.m2e.jdt.internal.BuildPathManager.updateClasspath(BuildPathManager.java:191)
at org.eclipse.m2e.jdt.internal.BuildPathManager.mavenProjectChanged(BuildPathManager.java:180)
at org.eclipse.m2e.core.internal.project.registry.ProjectRegistryManager.notifyProjectChangeListeners(ProjectRegistryManager.java:746)
at org.eclipse.m2e.core.internal.project.registry.ProjectRegistryManager.applyMutableProjectRegistry(ProjectRegistryManager.java:865)
at org.eclipse.m2e.core.internal.project.registry.ProjectRegistryManager.refresh(ProjectRegistryManager.java:289)
at org.eclipse.m2e.core.internal.project.ProjectConfigurationManager.updateProjectConfiguration0(ProjectConfigurationManager.java:369)
at org.eclipse.m2e.core.internal.project.ProjectConfigurationManager$2.call(ProjectConfigurationManager.java:316)
at org.eclipse.m2e.core.internal.project.ProjectConfigurationManager$2.call(ProjectConfigurationManager.java:1)
at org.eclipse.m2e.core.internal.embedder.MavenExecutionContext.executeBare(MavenExecutionContext.java:161)
at org.eclipse.m2e.core.internal.embedder.MavenExecutionContext.execute(MavenExecutionContext.java:137)
at org.eclipse.m2e.core.internal.embedder.MavenExecutionContext.execute(MavenExecutionContext.java:89)
at org.eclipse.m2e.core.internal.embedder.MavenImpl.execute(MavenImpl.java:1301)
at org.eclipse.m2e.core.internal.project.ProjectConfigurationManager.updateProjectConfiguration(ProjectConfigurationManager.java:313)
at org.eclipse.m2e.core.ui.internal.UpdateMavenProjectJob.runInWorkspace(UpdateMavenProjectJob.java:77)
at org.eclipse.core.internal.resources.InternalWorkspaceJob.run(InternalWorkspaceJob.java:38)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:53)
Run Code Online (Sandbox Code Playgroud)
这是我尝试过的:
给定一个包含压缩格式的音频数据(如MP3或OGG)的InputStream
调用in
,我希望创建一个byte
包含输入数据的WAV转换的数组.不幸的是,如果您尝试这样做,JavaSound会向您发出以下错误:
java.io.IOException: stream length not specified
Run Code Online (Sandbox Code Playgroud)
我设法通过将wav写入临时文件然后将其重新读入来使其工作,如下所示:
AudioInputStream source = AudioSystem.getAudioInputStream(new BufferedInputStream(in, 1024));
AudioInputStream pcm = AudioSystem.getAudioInputStream(AudioFormat.Encoding.PCM_SIGNED, source);
AudioInputStream ulaw = AudioSystem.getAudioInputStream(AudioFormat.Encoding.ULAW, pcm);
File tempFile = File.createTempFile("wav", "tmp");
AudioSystem.write(ulaw, AudioFileFormat.Type.WAVE, tempFile);
// The fileToByteArray() method reads the file
// into a byte array; omitted for brevity
byte[] bytes = fileToByteArray(tempFile);
tempFile.delete();
return bytes;
Run Code Online (Sandbox Code Playgroud)
这显然不太理想.有没有更好的办法?
我试图让这个玩家可以ASK [PERSON] ABOUT [TOPIC]
,TELL [PERSON] ABOUT [TOPIC]
或THINK ABOUT [TOPIC]
在通知7.我开始喜欢这个建模THINK ABOUT [TOPIC]
:
主题是一种东西.主题已知或未知.一个主题通常是未知的.
思考是一种适用于一件事的行为.理解"思考[某事]"是一种思考.理解"思考[某事]"是一种思考.
进行思考:如果名词是一个主题,请改为"[名词描述]".
但后来我才意识到,我可能希望使用相同的机制来思考抽象主题和具体事物.我还遇到了一个问题,即除非主题是房间中的具体内容,否则Inform认为它超出了范围.我不知道如何解决这个问题.与此同时,我确实希望大多数主题从范围开始,但是在前面的主题建议的范围内.
在思考我想要实现的目标时,它似乎与Emily Short等人使用的系统非常相似.人.在Alabaster.源导入一个名为Threaded Conversation的扩展,但我看不出它来自哪里.
简而言之,我需要一个会话系统:
我的 Tapestry 应用程序中的登录页面有一个属性,其中存储了用户键入的密码,然后将其与数据库中的值进行比较。如果用户输入多字节字符的密码,例如:
áéíóú
Run Code Online (Sandbox Code Playgroud)
...检查 getPassword()(相应属性的抽象方法)的返回值给出:
áéÃóú
Run Code Online (Sandbox Code Playgroud)
显然,这没有正确编码。然而,Firebug 报告该页面以 UTF-8 格式提供,因此表单提交请求可能也会以 UTF-8 编码。检查来自数据库的值会生成正确的字符串,因此它看起来不是操作系统或 IDE 编码问题。我没有在 .application 文件中覆盖 Tapestry 的 org.apache.tapestry.output-encoding 默认值,Tapestry 4文档表明该属性的默认值是 UTF-8。
那么为什么 Tapestry 在设置属性时会出现编码错误呢?
相关代码如下:
áéíóú
Run Code Online (Sandbox Code Playgroud)
áéÃóú
Run Code Online (Sandbox Code Playgroud)
...
public abstract class Login extends BasePage {
...
public abstract String getPassword();
...
public void attemptLogin() {
// At this point, inspecting getPassword() returns
// the incorrectly encoded String.
}
...
}
Run Code Online (Sandbox Code Playgroud)
@Jan Soltis:好吧,如果我检查来自数据库的值,它会显示正确的字符串,所以看起来我的编辑器、操作系统和数据库都正确地对值进行了编码。我还检查了我的 .application 文件;它不包含 org.apache.tapestry.output-encoding 条目,Tapestry 4文档表明该属性的默认值为 UTF-8。我已更新上述说明以反映您问题的答案。
@myself:找到解决方案。
(出于这个问题的目的,让我们假设一个人故意不使用自动(非)拳击,因为一个人正在编写Java 1.5之前的代码,或者因为一个人认为自动装箱使得创建NullPointerException
s 太容易了.)
就拿Boolean
,例如.Boolean(boolean)
构造函数的文档说:
注意:使用此构造函数很少是合适的.除非需要新 实例,否则静态工厂
valueOf(boolean)
通常是更好的选择.它可能会产生明显更好的空间和时间性能.
我的问题是,为什么你永远要摆在首位获得一个新的实例?如果像这样的构造函数是私有的,那么事情似乎会更简单.例如,如果它们是,你可以写这个没有危险(即使myBoolean
是null
):
if (myBoolean == Boolean.TRUE)
Run Code Online (Sandbox Code Playgroud)
它是安全的,因为所有的真实Booleans
都是引用Boolean.TRUE
,所有的错误Booleans
都是引用Boolean.FALSE
.但是因为构造函数是公共的,所以有人可能已经使用过它们,这意味着你必须编写它:
if (Boolean.TRUE.equals(myBoolean))
Run Code Online (Sandbox Code Playgroud)
但真正变坏的地方在于你想要检查两个Booleans
是否平等.像这样的东西:
if (myBooleanA == myBooleanB)
Run Code Online (Sandbox Code Playgroud)
......变成这个:
if (
myBooleanA == myBooleanB ||
(myBooleanA != null && myBooleanA.equals(myBooleanB))
)
Run Code Online (Sandbox Code Playgroud)
更新:随着Java 7的发布,java.util.Objects使这个更简单的构造成为可能:
if (Objects.equals(myBooleanA, myBooleanB))
Run Code Online (Sandbox Code Playgroud)
我想不出有任何理由让这些对象具有单独的实例,这比不必做上面的废话更有说服力.怎么说你?
我有一个GWT应用程序,显示由JFreeChart呈现的一些图表.每隔几分钟,页面刷新一次,这会导致应用程序生成新图表.(换句话说,整个图表生成过程由客户端请求引导.)问题是多个客户端命中同一个服务器会导致生成图表的多个请求,但由于所有用户的图表相同,真的没有理由这样做.我想在后台线程中预先渲染图表,这将在应用程序启动时启动,然后根据请求将已呈现的图表提供给客户端.
我没有在GWT中看到任何"认可"的方式来在服务器启动时执行您自己的代码.我能想到的唯一方法是创建一个servlet,它在应用程序容器启动时加载,并在init()方法中启动图表生成线程.
有更优选的方法吗?
注意:假设这是真的,"不"是一个完全可以接受的答案.
我正在努力使用AngularJS验证.这是我在HTML 5中的SSCCE(由于我的服务器端框架,它必须是有效的XML):
HTML
<div ng-app="">
<form name="myForm" ng-controller="ValidationTest" novalidate="novalidate">
<input name="email" ng-model="myForm.email" type="email" required="required" />
<div>
Field:
<span ng-show="myForm.email.$valid">valid</span>
<span ng-show="myForm.email.$invalid">invalid</span>
<span ng-show="myForm.email.$pristine">pristine</span>
<span ng-show="myForm.email.$dirty">dirty</span>
</div>
<div>
Form:
<span ng-show="myForm.$valid">valid</span>
<span ng-show="myForm.$invalid">invalid</span>
<span ng-show="myForm.$pristine">pristine</span>
<span ng-show="myForm.$dirty">dirty</span>
</div>
</form>
</div>
Run Code Online (Sandbox Code Playgroud)
CSS
input.ng-valid {
border-color: #0f0;
}
input.ng-invalid {
border-color: #f00;
}
input.ng-pristine {
background-color: #eef;
}
input.ng-dirty {
background-color: #fee;
}
Run Code Online (Sandbox Code Playgroud)
JavaScript的
function ValidationTest($scope) {}
Run Code Online (Sandbox Code Playgroud)
当我运行这个场景时,应用于表单元素的CSS类正确地反映了它的验证状态,表单的ng-show指令也是如此.但是,该字段的ng-show指令开始正确(显示"无效"和"原始")但是一旦我开始在字段中键入,所有指令都会消失.据我所知,我正如文档所示这样做,所以有什么不对?
我使用Tapestry 4,每当我们推出一个更改任何资产(图像,样式表,JS库)的版本时,我们就会遇到问题,因为用户的浏览器缓存中仍然有旧版本的资产.我想设置一些简单的方法来允许缓存,但在更新应用程序时强制下载新的资产.简单地完全不允许缓存资产是不可接受的解决方案.
我没有看到任何现有的机制,但我想到可能有一些方法告诉Tapestry将内部版本号添加到URL,如下所示:
http://www.test.com/path/to/the/asset/asset.jpg?12345
这样,每个新构建都会使它看起来像最终用户的不同资产.
Tapestry是否提供了一种解决我不知道的缓存问题的简单方法?如果没有,如何修改Tapestry生成的URL?负责这样做的代码如何获得内部版本号?(例如,我可以将构建号编入Spring bean,但是新的URL构建机制将如何获得它?)
假设您有以下字符串:
white sand, tall waves, warm sun
Run Code Online (Sandbox Code Playgroud)
编写一个与分隔符匹配的正则表达式很容易,Java String.split()方法可以使用它来为你提供一个包含标记"white sand","tall waves"和"warm sun"的数组:
\s*,\s*
Run Code Online (Sandbox Code Playgroud)
现在说你有这个字符串:
white sand and tall waves and warm sun
Run Code Online (Sandbox Code Playgroud)
再一次,分割令牌的正则表达式很容易(确保你没有得到"和"字里面的"和"):
\s+and\s+
Run Code Online (Sandbox Code Playgroud)
现在,考虑这个字符串:
white sand, tall waves and warm sun
Run Code Online (Sandbox Code Playgroud)
是否可以正确编写与正确分隔符匹配的正则表达式,允许您将字符串拆分为与前两种情况相同的标记?或者,可以编写一个与令牌本身匹配的正则表达式并省略分隔符吗?(逗号两侧的任何数量的空格或"and"一词都应视为分隔符的一部分.)
编辑:正如评论中指出的那样,正确的答案应该在输入字符串的开头或结尾处有效地处理分隔符.在理想的答案应该能够采取像"白色的沙滩,高大的海浪和温暖的阳光和"字符串,并提供这些准确的三个令牌:
[ "white sand", "tall waves", "warm sun" ]
Run Code Online (Sandbox Code Playgroud)
......没有 额外的空标记或 任何令牌的开头或结尾都有额外的空格.
编辑:有人指出使用String.split()是不可避免的额外空标记,所以这已被删除作为"完美"正则表达式的标准.
感谢大家的回应!我试图确保我对所有提供可行的正则表达式的人进行了投票,而这些正则表达式本质上并不重复.丹的答案是最强大的(它甚至处理",白色的沙子,高大的波浪和温暖的阳光",合理地说,在"波浪"这个词之后用奇怪的逗号放置),所以我将他标记为已接受的答案.nsayer提供的正则表达式紧随其后.
java ×7
javascript ×2
tapestry ×2
angularjs ×1
audio ×1
browser ×1
caching ×1
classloader ×1
constructor ×1
dom ×1
eclipse ×1
firefox ×1
greasemonkey ×1
gwt ×1
html5 ×1
immutability ×1
inform7 ×1
javasound ×1
junit ×1
leaflet ×1
maven ×1
regex ×1
validation ×1
wav ×1